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
|
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_OBJECTS_H_
#define V8_OBJECTS_H_
#include "allocation.h"
#include "builtins.h"
#include "elements-kind.h"
#include "list.h"
#include "property-details.h"
#include "smart-pointers.h"
#include "unicode-inl.h"
#if V8_TARGET_ARCH_ARM
#include "arm/constants-arm.h"
#elif V8_TARGET_ARCH_PPC
#include "ppc/constants-ppc.h"
#elif V8_TARGET_ARCH_MIPS
#include "mips/constants-mips.h"
#endif
#include "v8checks.h"
#include "zone.h"
//
// Most object types in the V8 JavaScript are described in this file.
//
// Inheritance hierarchy:
// - MaybeObject (an object or a failure)
// - Failure (immediate for marking failed operation)
// - Object
// - Smi (immediate small integer)
// - HeapObject (superclass for everything allocated in the heap)
// - JSReceiver (suitable for property access)
// - JSObject
// - JSArray
// - JSSet
// - JSMap
// - JSWeakMap
// - JSRegExp
// - JSFunction
// - JSModule
// - GlobalObject
// - JSGlobalObject
// - JSBuiltinsObject
// - JSGlobalProxy
// - JSValue
// - JSDate
// - JSMessageObject
// - JSProxy
// - JSFunctionProxy
// - FixedArrayBase
// - ByteArray
// - FixedArray
// - DescriptorArray
// - HashTable
// - Dictionary
// - SymbolTable
// - CompilationCacheTable
// - CodeCacheHashTable
// - MapCache
// - Context
// - JSFunctionResultCache
// - ScopeInfo
// - TransitionArray
// - FixedDoubleArray
// - ExternalArray
// - ExternalPixelArray
// - ExternalByteArray
// - ExternalUnsignedByteArray
// - ExternalShortArray
// - ExternalUnsignedShortArray
// - ExternalIntArray
// - ExternalUnsignedIntArray
// - ExternalFloatArray
// - String
// - SeqString
// - SeqAsciiString
// - SeqTwoByteString
// - SlicedString
// - ConsString
// - ExternalString
// - ExternalAsciiString
// - ExternalTwoByteString
// - HeapNumber
// - Code
// - Map
// - Oddball
// - Foreign
// - SharedFunctionInfo
// - Struct
// - AccessorInfo
// - AccessorPair
// - AccessCheckInfo
// - InterceptorInfo
// - CallHandlerInfo
// - TemplateInfo
// - FunctionTemplateInfo
// - ObjectTemplateInfo
// - Script
// - SignatureInfo
// - TypeSwitchInfo
// - DebugInfo
// - BreakPointInfo
// - CodeCache
//
// Formats of Object*:
// Smi: [31 bit signed int] 0
// HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
// Failure: [30 bit signed int] 11
namespace v8 {
namespace internal {
enum CompareMapMode {
REQUIRE_EXACT_MAP,
ALLOW_ELEMENT_TRANSITION_MAPS
};
enum KeyedAccessGrowMode {
DO_NOT_ALLOW_JSARRAY_GROWTH,
ALLOW_JSARRAY_GROWTH
};
// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
// PropertyNormalizationMode is used to specify whether to keep
// inobject properties when normalizing properties of a JSObject.
enum PropertyNormalizationMode {
CLEAR_INOBJECT_PROPERTIES,
KEEP_INOBJECT_PROPERTIES
};
// NormalizedMapSharingMode is used to specify whether a map may be shared
// by different objects with normalized properties.
enum NormalizedMapSharingMode {
UNIQUE_NORMALIZED_MAP,
SHARED_NORMALIZED_MAP
};
// Indicates whether a get method should implicitly create the object looked up.
enum CreationFlag {
ALLOW_CREATION,
OMIT_CREATION
};
// Indicates whether transitions can be added to a source map or not.
enum TransitionFlag {
INSERT_TRANSITION,
OMIT_TRANSITION
};
// Indicates whether the transition is simple: the target map of the transition
// either extends the current map with a new property, or it modifies the
// property that was added last to the current map.
enum SimpleTransitionFlag {
SIMPLE_TRANSITION,
FULL_TRANSITION
};
// Indicates whether we are only interested in the descriptors of a particular
// map, or in all descriptors in the descriptor array.
enum DescriptorFlag {
ALL_DESCRIPTORS,
OWN_DESCRIPTORS
};
// Instance size sentinel for objects of variable size.
const int kVariableSizeSentinel = 0;
const int kStubMajorKeyBits = 6;
const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
// All Maps have a field instance_type containing a InstanceType.
// It describes the type of the instances.
//
// As an example, a JavaScript object is a heap object and its map
// instance_type is JS_OBJECT_TYPE.
//
// The names of the string instance types are intended to systematically
// mirror their encoding in the instance_type field of the map. The default
// encoding is considered TWO_BYTE. It is not mentioned in the name. ASCII
// encoding is mentioned explicitly in the name. Likewise, the default
// representation is considered sequential. It is not mentioned in the
// name. The other representations (e.g. CONS, EXTERNAL) are explicitly
// mentioned. Finally, the string is either a SYMBOL_TYPE (if it is a
// symbol) or a STRING_TYPE (if it is not a symbol).
//
// NOTE: The following things are some that depend on the string types having
// instance_types that are less than those of all other types:
// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
// Object::IsString.
//
// NOTE: Everything following JS_VALUE_TYPE is considered a
// JSObject for GC purposes. The first four entries here have typeof
// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
#define INSTANCE_TYPE_LIST_ALL(V) \
V(SYMBOL_TYPE) \
V(ASCII_SYMBOL_TYPE) \
V(CONS_SYMBOL_TYPE) \
V(CONS_ASCII_SYMBOL_TYPE) \
V(EXTERNAL_SYMBOL_TYPE) \
V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
V(EXTERNAL_ASCII_SYMBOL_TYPE) \
V(SHORT_EXTERNAL_SYMBOL_TYPE) \
V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE) \
V(STRING_TYPE) \
V(ASCII_STRING_TYPE) \
V(CONS_STRING_TYPE) \
V(CONS_ASCII_STRING_TYPE) \
V(SLICED_STRING_TYPE) \
V(EXTERNAL_STRING_TYPE) \
V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
V(EXTERNAL_ASCII_STRING_TYPE) \
V(SHORT_EXTERNAL_STRING_TYPE) \
V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
V(SHORT_EXTERNAL_ASCII_STRING_TYPE) \
V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
\
V(MAP_TYPE) \
V(CODE_TYPE) \
V(ODDBALL_TYPE) \
V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
\
V(HEAP_NUMBER_TYPE) \
V(FOREIGN_TYPE) \
V(BYTE_ARRAY_TYPE) \
V(FREE_SPACE_TYPE) \
/* Note: the order of these external array */ \
/* types is relied upon in */ \
/* Object::IsExternalArray(). */ \
V(EXTERNAL_BYTE_ARRAY_TYPE) \
V(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE) \
V(EXTERNAL_SHORT_ARRAY_TYPE) \
V(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE) \
V(EXTERNAL_INT_ARRAY_TYPE) \
V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) \
V(EXTERNAL_FLOAT_ARRAY_TYPE) \
V(EXTERNAL_PIXEL_ARRAY_TYPE) \
V(FILLER_TYPE) \
\
V(ACCESSOR_INFO_TYPE) \
V(ACCESSOR_PAIR_TYPE) \
V(ACCESS_CHECK_INFO_TYPE) \
V(INTERCEPTOR_INFO_TYPE) \
V(CALL_HANDLER_INFO_TYPE) \
V(FUNCTION_TEMPLATE_INFO_TYPE) \
V(OBJECT_TEMPLATE_INFO_TYPE) \
V(SIGNATURE_INFO_TYPE) \
V(TYPE_SWITCH_INFO_TYPE) \
V(SCRIPT_TYPE) \
V(CODE_CACHE_TYPE) \
V(POLYMORPHIC_CODE_CACHE_TYPE) \
V(TYPE_FEEDBACK_INFO_TYPE) \
V(ALIASED_ARGUMENTS_ENTRY_TYPE) \
\
V(FIXED_ARRAY_TYPE) \
V(FIXED_DOUBLE_ARRAY_TYPE) \
V(SHARED_FUNCTION_INFO_TYPE) \
\
V(JS_MESSAGE_OBJECT_TYPE) \
\
V(JS_VALUE_TYPE) \
V(JS_DATE_TYPE) \
V(JS_OBJECT_TYPE) \
V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
V(JS_MODULE_TYPE) \
V(JS_GLOBAL_OBJECT_TYPE) \
V(JS_BUILTINS_OBJECT_TYPE) \
V(JS_GLOBAL_PROXY_TYPE) \
V(JS_ARRAY_TYPE) \
V(JS_PROXY_TYPE) \
V(JS_WEAK_MAP_TYPE) \
V(JS_REGEXP_TYPE) \
\
V(JS_FUNCTION_TYPE) \
V(JS_FUNCTION_PROXY_TYPE) \
#ifdef ENABLE_DEBUGGER_SUPPORT
#define INSTANCE_TYPE_LIST_DEBUGGER(V) \
V(DEBUG_INFO_TYPE) \
V(BREAK_POINT_INFO_TYPE)
#else
#define INSTANCE_TYPE_LIST_DEBUGGER(V)
#endif
#define INSTANCE_TYPE_LIST(V) \
INSTANCE_TYPE_LIST_ALL(V) \
INSTANCE_TYPE_LIST_DEBUGGER(V)
// Since string types are not consecutive, this macro is used to
// iterate over them.
#define STRING_TYPE_LIST(V) \
V(SYMBOL_TYPE, \
kVariableSizeSentinel, \
symbol, \
Symbol) \
V(ASCII_SYMBOL_TYPE, \
kVariableSizeSentinel, \
ascii_symbol, \
AsciiSymbol) \
V(CONS_SYMBOL_TYPE, \
ConsString::kSize, \
cons_symbol, \
ConsSymbol) \
V(CONS_ASCII_SYMBOL_TYPE, \
ConsString::kSize, \
cons_ascii_symbol, \
ConsAsciiSymbol) \
V(EXTERNAL_SYMBOL_TYPE, \
ExternalTwoByteString::kSize, \
external_symbol, \
ExternalSymbol) \
V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
ExternalTwoByteString::kSize, \
external_symbol_with_ascii_data, \
ExternalSymbolWithAsciiData) \
V(EXTERNAL_ASCII_SYMBOL_TYPE, \
ExternalAsciiString::kSize, \
external_ascii_symbol, \
ExternalAsciiSymbol) \
V(SHORT_EXTERNAL_SYMBOL_TYPE, \
ExternalTwoByteString::kShortSize, \
short_external_symbol, \
ShortExternalSymbol) \
V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
ExternalTwoByteString::kShortSize, \
short_external_symbol_with_ascii_data, \
ShortExternalSymbolWithAsciiData) \
V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE, \
ExternalAsciiString::kShortSize, \
short_external_ascii_symbol, \
ShortExternalAsciiSymbol) \
V(STRING_TYPE, \
kVariableSizeSentinel, \
string, \
String) \
V(ASCII_STRING_TYPE, \
kVariableSizeSentinel, \
ascii_string, \
AsciiString) \
V(CONS_STRING_TYPE, \
ConsString::kSize, \
cons_string, \
ConsString) \
V(CONS_ASCII_STRING_TYPE, \
ConsString::kSize, \
cons_ascii_string, \
ConsAsciiString) \
V(SLICED_STRING_TYPE, \
SlicedString::kSize, \
sliced_string, \
SlicedString) \
V(SLICED_ASCII_STRING_TYPE, \
SlicedString::kSize, \
sliced_ascii_string, \
SlicedAsciiString) \
V(EXTERNAL_STRING_TYPE, \
ExternalTwoByteString::kSize, \
external_string, \
ExternalString) \
V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
ExternalTwoByteString::kSize, \
external_string_with_ascii_data, \
ExternalStringWithAsciiData) \
V(EXTERNAL_ASCII_STRING_TYPE, \
ExternalAsciiString::kSize, \
external_ascii_string, \
ExternalAsciiString) \
V(SHORT_EXTERNAL_STRING_TYPE, \
ExternalTwoByteString::kShortSize, \
short_external_string, \
ShortExternalString) \
V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
ExternalTwoByteString::kShortSize, \
short_external_string_with_ascii_data, \
ShortExternalStringWithAsciiData) \
V(SHORT_EXTERNAL_ASCII_STRING_TYPE, \
ExternalAsciiString::kShortSize, \
short_external_ascii_string, \
ShortExternalAsciiString)
// A struct is a simple object a set of object-valued fields. Including an
// object type in this causes the compiler to generate most of the boilerplate
// code for the class including allocation and garbage collection routines,
// casts and predicates. All you need to define is the class, methods and
// object verification routines. Easy, no?
//
// Note that for subtle reasons related to the ordering or numerical values of
// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
// manually.
#define STRUCT_LIST_ALL(V) \
V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \
V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
V(SIGNATURE_INFO, SignatureInfo, signature_info) \
V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
V(SCRIPT, Script, script) \
V(CODE_CACHE, CodeCache, code_cache) \
V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache) \
V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info) \
V(ALIASED_ARGUMENTS_ENTRY, AliasedArgumentsEntry, aliased_arguments_entry)
#ifdef ENABLE_DEBUGGER_SUPPORT
#define STRUCT_LIST_DEBUGGER(V) \
V(DEBUG_INFO, DebugInfo, debug_info) \
V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
#else
#define STRUCT_LIST_DEBUGGER(V)
#endif
#define STRUCT_LIST(V) \
STRUCT_LIST_ALL(V) \
STRUCT_LIST_DEBUGGER(V)
// We use the full 8 bits of the instance_type field to encode heap object
// instance types. The high-order bit (bit 7) is set if the object is not a
// string, and cleared if it is a string.
const uint32_t kIsNotStringMask = 0x80;
const uint32_t kStringTag = 0x0;
const uint32_t kNotStringTag = 0x80;
// Bit 6 indicates that the object is a symbol (if set) or not (if cleared).
// There are not enough types that the non-string types (with bit 7 set) can
// have bit 6 set too.
const uint32_t kIsSymbolMask = 0x40;
const uint32_t kNotSymbolTag = 0x0;
const uint32_t kSymbolTag = 0x40;
// If bit 7 is clear then bit 2 indicates whether the string consists of
// two-byte characters or one-byte characters.
const uint32_t kStringEncodingMask = 0x4;
const uint32_t kTwoByteStringTag = 0x0;
const uint32_t kAsciiStringTag = 0x4;
// If bit 7 is clear, the low-order 2 bits indicate the representation
// of the string.
const uint32_t kStringRepresentationMask = 0x03;
enum StringRepresentationTag {
kSeqStringTag = 0x0,
kConsStringTag = 0x1,
kExternalStringTag = 0x2,
kSlicedStringTag = 0x3
};
const uint32_t kIsIndirectStringMask = 0x1;
const uint32_t kIsIndirectStringTag = 0x1;
STATIC_ASSERT((kSeqStringTag & kIsIndirectStringMask) == 0);
STATIC_ASSERT((kExternalStringTag & kIsIndirectStringMask) == 0);
STATIC_ASSERT(
(kConsStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
STATIC_ASSERT(
(kSlicedStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
// Use this mask to distinguish between cons and slice only after making
// sure that the string is one of the two (an indirect string).
const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
// If bit 7 is clear, then bit 3 indicates whether this two-byte
// string actually contains ASCII data.
const uint32_t kAsciiDataHintMask = 0x08;
const uint32_t kAsciiDataHintTag = 0x08;
// If bit 7 is clear and string representation indicates an external string,
// then bit 4 indicates whether the data pointer is cached.
const uint32_t kShortExternalStringMask = 0x10;
const uint32_t kShortExternalStringTag = 0x10;
// A ConsString with an empty string as the right side is a candidate
// for being shortcut by the garbage collector unless it is a
// symbol. It's not common to have non-flat symbols, so we do not
// shortcut them thereby avoiding turning symbols into strings. See
// heap.cc and mark-compact.cc.
const uint32_t kShortcutTypeMask =
kIsNotStringMask |
kIsSymbolMask |
kStringRepresentationMask;
const uint32_t kShortcutTypeTag = kConsStringTag;
enum InstanceType {
// String types.
SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kSeqStringTag,
ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
SHORT_EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag |
kExternalStringTag | kShortExternalStringTag,
SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
kTwoByteStringTag | kSymbolTag | kExternalStringTag |
kAsciiDataHintTag | kShortExternalStringTag,
SHORT_EXTERNAL_ASCII_SYMBOL_TYPE = kAsciiStringTag | kExternalStringTag |
kSymbolTag | kShortExternalStringTag,
EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
EXTERNAL_ASCII_SYMBOL_TYPE =
kAsciiStringTag | kSymbolTag | kExternalStringTag,
STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
ASCII_STRING_TYPE = kAsciiStringTag | kSeqStringTag,
CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
SLICED_STRING_TYPE = kTwoByteStringTag | kSlicedStringTag,
SLICED_ASCII_STRING_TYPE = kAsciiStringTag | kSlicedStringTag,
SHORT_EXTERNAL_STRING_TYPE =
kTwoByteStringTag | kExternalStringTag | kShortExternalStringTag,
SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
kTwoByteStringTag | kExternalStringTag |
kAsciiDataHintTag | kShortExternalStringTag,
SHORT_EXTERNAL_ASCII_STRING_TYPE =
kAsciiStringTag | kExternalStringTag | kShortExternalStringTag,
EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
// LAST_STRING_TYPE
EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag,
PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
// Objects allocated in their own spaces (never in new space).
MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
CODE_TYPE,
ODDBALL_TYPE,
JS_GLOBAL_PROPERTY_CELL_TYPE,
// "Data", objects that cannot contain non-map-word pointers to heap
// objects.
HEAP_NUMBER_TYPE,
FOREIGN_TYPE,
BYTE_ARRAY_TYPE,
FREE_SPACE_TYPE,
EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
EXTERNAL_SHORT_ARRAY_TYPE,
EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
EXTERNAL_INT_ARRAY_TYPE,
EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
EXTERNAL_FLOAT_ARRAY_TYPE,
EXTERNAL_DOUBLE_ARRAY_TYPE,
EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
FIXED_DOUBLE_ARRAY_TYPE,
FILLER_TYPE, // LAST_DATA_TYPE
// Structs.
ACCESSOR_INFO_TYPE,
ACCESSOR_PAIR_TYPE,
ACCESS_CHECK_INFO_TYPE,
INTERCEPTOR_INFO_TYPE,
CALL_HANDLER_INFO_TYPE,
FUNCTION_TEMPLATE_INFO_TYPE,
OBJECT_TEMPLATE_INFO_TYPE,
SIGNATURE_INFO_TYPE,
TYPE_SWITCH_INFO_TYPE,
SCRIPT_TYPE,
CODE_CACHE_TYPE,
POLYMORPHIC_CODE_CACHE_TYPE,
TYPE_FEEDBACK_INFO_TYPE,
ALIASED_ARGUMENTS_ENTRY_TYPE,
// The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT
// is defined. However as include/v8.h contain some of the instance type
// constants always having them avoids them getting different numbers
// depending on whether ENABLE_DEBUGGER_SUPPORT is defined or not.
DEBUG_INFO_TYPE,
BREAK_POINT_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
JS_MESSAGE_OBJECT_TYPE,
// All the following types are subtypes of JSReceiver, which corresponds to
// objects in the JS sense. The first and the last type in this range are
// the two forms of function. This organization enables using the same
// compares for checking the JS_RECEIVER/SPEC_OBJECT range and the
// NONCALLABLE_JS_OBJECT range.
JS_FUNCTION_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE, FIRST_JS_PROXY_TYPE
JS_PROXY_TYPE, // LAST_JS_PROXY_TYPE
JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
JS_DATE_TYPE,
JS_OBJECT_TYPE,
JS_CONTEXT_EXTENSION_OBJECT_TYPE,
JS_MODULE_TYPE,
JS_GLOBAL_OBJECT_TYPE,
JS_BUILTINS_OBJECT_TYPE,
JS_GLOBAL_PROXY_TYPE,
JS_ARRAY_TYPE,
JS_SET_TYPE,
JS_MAP_TYPE,
JS_WEAK_MAP_TYPE,
JS_REGEXP_TYPE,
JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE
// Pseudo-types
FIRST_TYPE = 0x0,
LAST_TYPE = JS_FUNCTION_TYPE,
INVALID_TYPE = FIRST_TYPE - 1,
FIRST_NONSTRING_TYPE = MAP_TYPE,
// Boundaries for testing for an external array.
FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
// Boundary for promotion to old data space/old pointer space.
LAST_DATA_TYPE = FILLER_TYPE,
// Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
// Note that there is no range for JSObject or JSProxy, since their subtypes
// are not continuous in this enum! The enum ranges instead reflect the
// external class names, where proxies are treated as either ordinary objects,
// or functions.
FIRST_JS_RECEIVER_TYPE = JS_FUNCTION_PROXY_TYPE,
LAST_JS_RECEIVER_TYPE = LAST_TYPE,
// Boundaries for testing the types represented as JSObject
FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
LAST_JS_OBJECT_TYPE = LAST_TYPE,
// Boundaries for testing the types represented as JSProxy
FIRST_JS_PROXY_TYPE = JS_FUNCTION_PROXY_TYPE,
LAST_JS_PROXY_TYPE = JS_PROXY_TYPE,
// Boundaries for testing whether the type is a JavaScript object.
FIRST_SPEC_OBJECT_TYPE = FIRST_JS_RECEIVER_TYPE,
LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE,
// Boundaries for testing the types for which typeof is "object".
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_PROXY_TYPE,
LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE,
// Note that the types for which typeof is "function" are not continuous.
// Define this so that we can put assertions on discrete checks.
NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2
};
const int kExternalArrayTypeCount =
LAST_EXTERNAL_ARRAY_TYPE - FIRST_EXTERNAL_ARRAY_TYPE + 1;
STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
STATIC_CHECK(ODDBALL_TYPE == Internals::kOddballType);
STATIC_CHECK(FOREIGN_TYPE == Internals::kForeignType);
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
V(FAST_ELEMENTS_SUB_TYPE) \
V(DICTIONARY_ELEMENTS_SUB_TYPE) \
V(FAST_PROPERTIES_SUB_TYPE) \
V(DICTIONARY_PROPERTIES_SUB_TYPE) \
V(MAP_CODE_CACHE_SUB_TYPE) \
V(SCOPE_INFO_SUB_TYPE) \
V(SYMBOL_TABLE_SUB_TYPE) \
V(DESCRIPTOR_ARRAY_SUB_TYPE) \
V(TRANSITION_ARRAY_SUB_TYPE)
enum FixedArraySubInstanceType {
#define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
LAST_FIXED_ARRAY_SUB_TYPE = TRANSITION_ARRAY_SUB_TYPE
};
enum CompareResult {
LESS = -1,
EQUAL = 0,
GREATER = 1,
NOT_EQUAL = GREATER
};
#define DECL_BOOLEAN_ACCESSORS(name) \
inline bool name(); \
inline void set_##name(bool value); \
#define DECL_ACCESSORS(name, type) \
inline type* name(); \
inline void set_##name(type* value, \
WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
class AccessorPair;
class DictionaryElementsAccessor;
class ElementsAccessor;
class Failure;
class FixedArrayBase;
class ObjectVisitor;
class StringStream;
struct ValueInfo : public Malloced {
ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
InstanceType type;
Object* ptr;
const char* str;
double number;
};
// A template-ized version of the IsXXX functions.
template <class C> static inline bool Is(Object* obj);
#ifdef VERIFY_HEAP
#define DECLARE_VERIFIER(Name) void Name##Verify();
#else
#define DECLARE_VERIFIER(Name)
#endif
class MaybeObject BASE_EMBEDDED {
public:
inline bool IsFailure();
inline bool IsRetryAfterGC();
inline bool IsOutOfMemory();
inline bool IsException();
INLINE(bool IsTheHole());
inline bool ToObject(Object** obj) {
if (IsFailure()) return false;
*obj = reinterpret_cast<Object*>(this);
return true;
}
inline Failure* ToFailureUnchecked() {
ASSERT(IsFailure());
return reinterpret_cast<Failure*>(this);
}
inline Object* ToObjectUnchecked() {
ASSERT(!IsFailure());
return reinterpret_cast<Object*>(this);
}
inline Object* ToObjectChecked() {
CHECK(!IsFailure());
return reinterpret_cast<Object*>(this);
}
template<typename T>
inline bool To(T** obj) {
if (IsFailure()) return false;
*obj = T::cast(reinterpret_cast<Object*>(this));
return true;
}
#ifdef OBJECT_PRINT
// Prints this object with details.
inline void Print() {
Print(stdout);
}
inline void PrintLn() {
PrintLn(stdout);
}
void Print(FILE* out);
void PrintLn(FILE* out);
#endif
#ifdef VERIFY_HEAP
// Verifies the object.
void Verify();
#endif
};
#define OBJECT_TYPE_LIST(V) \
V(Smi) \
V(HeapObject) \
V(Number) \
#define HEAP_OBJECT_TYPE_LIST(V) \
V(HeapNumber) \
V(String) \
V(Symbol) \
V(SeqString) \
V(ExternalString) \
V(ConsString) \
V(SlicedString) \
V(ExternalTwoByteString) \
V(ExternalAsciiString) \
V(SeqTwoByteString) \
V(SeqAsciiString) \
\
V(ExternalArray) \
V(ExternalByteArray) \
V(ExternalUnsignedByteArray) \
V(ExternalShortArray) \
V(ExternalUnsignedShortArray) \
V(ExternalIntArray) \
V(ExternalUnsignedIntArray) \
V(ExternalFloatArray) \
V(ExternalDoubleArray) \
V(ExternalPixelArray) \
V(ByteArray) \
V(FreeSpace) \
V(JSReceiver) \
V(JSObject) \
V(JSContextExtensionObject) \
V(JSModule) \
V(Map) \
V(DescriptorArray) \
V(TransitionArray) \
V(DeoptimizationInputData) \
V(DeoptimizationOutputData) \
V(TypeFeedbackCells) \
V(FixedArray) \
V(FixedDoubleArray) \
V(Context) \
V(NativeContext) \
V(ScopeInfo) \
V(JSFunction) \
V(Code) \
V(Oddball) \
V(SharedFunctionInfo) \
V(JSValue) \
V(JSDate) \
V(JSMessageObject) \
V(StringWrapper) \
V(Foreign) \
V(Boolean) \
V(JSArray) \
V(JSProxy) \
V(JSFunctionProxy) \
V(JSSet) \
V(JSMap) \
V(JSWeakMap) \
V(JSRegExp) \
V(HashTable) \
V(Dictionary) \
V(SymbolTable) \
V(JSFunctionResultCache) \
V(NormalizedMapCache) \
V(CompilationCacheTable) \
V(CodeCacheHashTable) \
V(PolymorphicCodeCacheHashTable) \
V(MapCache) \
V(Primitive) \
V(GlobalObject) \
V(JSGlobalObject) \
V(JSBuiltinsObject) \
V(JSGlobalProxy) \
V(UndetectableObject) \
V(AccessCheckNeeded) \
V(JSGlobalPropertyCell) \
class JSReceiver;
// Object is the abstract superclass for all classes in the
// object hierarchy.
// Object does not use any virtual functions to avoid the
// allocation of the C++ vtable.
// Since Smi and Failure are subclasses of Object no
// data members can be present in Object.
class Object : public MaybeObject {
public:
// Type testing.
bool IsObject() { return true; }
#define IS_TYPE_FUNCTION_DECL(type_) inline bool Is##type_();
OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
#undef IS_TYPE_FUNCTION_DECL
inline bool IsFixedArrayBase();
// Returns true if this object is an instance of the specified
// function template.
inline bool IsInstanceOf(FunctionTemplateInfo* type);
inline bool IsStruct();
#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
#undef DECLARE_STRUCT_PREDICATE
INLINE(bool IsSpecObject());
INLINE(bool IsSpecFunction());
// Oddball testing.
INLINE(bool IsUndefined());
INLINE(bool IsNull());
INLINE(bool IsTheHole()); // Shadows MaybeObject's implementation.
INLINE(bool IsTrue());
INLINE(bool IsFalse());
inline bool IsArgumentsMarker();
inline bool NonFailureIsHeapObject();
// Filler objects (fillers and free space objects).
inline bool IsFiller();
// Extract the number.
inline double Number();
inline bool IsNaN();
// Returns true if the object is of the correct type to be used as a
// implementation of a JSObject's elements.
inline bool HasValidElements();
inline bool HasSpecificClassOf(String* name);
MUST_USE_RESULT MaybeObject* ToObject(); // ECMA-262 9.9.
Object* ToBoolean(); // ECMA-262 9.2.
// Convert to a JSObject if needed.
// native_context is used when creating wrapper object.
MUST_USE_RESULT MaybeObject* ToObject(Context* native_context);
// Converts this to a Smi if possible.
// Failure is returned otherwise.
MUST_USE_RESULT inline MaybeObject* ToSmi();
void Lookup(String* name, LookupResult* result);
// Property access.
MUST_USE_RESULT inline MaybeObject* GetProperty(String* key);
MUST_USE_RESULT inline MaybeObject* GetProperty(
String* key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
Object* receiver,
String* key,
PropertyAttributes* attributes);
static Handle<Object> GetProperty(Handle<Object> object,
Handle<Object> receiver,
LookupResult* result,
Handle<String> key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
LookupResult* result,
String* key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
JSReceiver* getter);
static Handle<Object> GetElement(Handle<Object> object, uint32_t index);
MUST_USE_RESULT inline MaybeObject* GetElement(uint32_t index);
// For use when we know that no exception can be thrown.
inline Object* GetElementNoExceptionThrown(uint32_t index);
MUST_USE_RESULT MaybeObject* GetElementWithReceiver(Object* receiver,
uint32_t index);
// Return the object's prototype (might be Heap::null_value()).
Object* GetPrototype();
// Returns the permanent hash code associated with this object depending on
// the actual object type. Might return a failure in case no hash was
// created yet or GC was caused by creation.
MUST_USE_RESULT MaybeObject* GetHash(CreationFlag flag);
// Checks whether this object has the same value as the given one. This
// function is implemented according to ES5, section 9.12 and can be used
// to implement the Harmony "egal" function.
bool SameValue(Object* other);
// Tries to convert an object to an array index. Returns true and sets
// the output parameter if it succeeds.
inline bool ToArrayIndex(uint32_t* index);
// Returns true if this is a JSValue containing a string and the index is
// < the length of the string. Used to implement [] on strings.
inline bool IsStringObjectWithCharacterAt(uint32_t index);
#ifdef VERIFY_HEAP
// Verify a pointer is a valid object pointer.
static void VerifyPointer(Object* p);
#endif
inline void VerifyApiCallResultType();
// Prints this object without details.
inline void ShortPrint() {
ShortPrint(stdout);
}
void ShortPrint(FILE* out);
// Prints this object without details to a message accumulator.
void ShortPrint(StringStream* accumulator);
// Casting: This cast is only needed to satisfy macros in objects-inl.h.
static Object* cast(Object* value) { return value; }
// Layout description.
static const int kHeaderSize = 0; // Object does not take up any space.
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
};
// Smi represents integer Numbers that can be stored in 31 bits.
// Smis are immediate which means they are NOT allocated in the heap.
// The this pointer has the following format: [31 bit signed int] 0
// For long smis it has the following format:
// [32 bit signed int] [31 bits zero padding] 0
// Smi stands for small integer.
class Smi: public Object {
public:
// Returns the integer value.
inline int value();
// Convert a value to a Smi object.
static inline Smi* FromInt(int value);
static inline Smi* FromIntptr(intptr_t value);
// Returns whether value can be represented in a Smi.
static inline bool IsValid(intptr_t value);
// Casting.
static inline Smi* cast(Object* object);
// Dispatched behavior.
inline void SmiPrint() {
SmiPrint(stdout);
}
void SmiPrint(FILE* out);
void SmiPrint(StringStream* accumulator);
DECLARE_VERIFIER(Smi)
static const int kMinValue =
(static_cast<unsigned int>(-1)) << (kSmiValueSize - 1);
static const int kMaxValue = -(kMinValue + 1);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
};
// Failure is used for reporting out of memory situations and
// propagating exceptions through the runtime system. Failure objects
// are transient and cannot occur as part of the object graph.
//
// Failures are a single word, encoded as follows:
// +-------------------------+---+--+--+
// |.........unused..........|sss|tt|11|
// +-------------------------+---+--+--+
// 7 6 4 32 10
//
//
// The low two bits, 0-1, are the failure tag, 11. The next two bits,
// 2-3, are a failure type tag 'tt' with possible values:
// 00 RETRY_AFTER_GC
// 01 EXCEPTION
// 10 INTERNAL_ERROR
// 11 OUT_OF_MEMORY_EXCEPTION
//
// The next three bits, 4-6, are an allocation space tag 'sss'. The
// allocation space tag is 000 for all failure types except
// RETRY_AFTER_GC. For RETRY_AFTER_GC, the possible values are the
// allocation spaces (the encoding is found in globals.h).
// Failure type tag info.
const int kFailureTypeTagSize = 2;
const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
class Failure: public MaybeObject {
public:
// RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
enum Type {
RETRY_AFTER_GC = 0,
EXCEPTION = 1, // Returning this marker tells the real exception
// is in Isolate::pending_exception.
INTERNAL_ERROR = 2,
OUT_OF_MEMORY_EXCEPTION = 3
};
inline Type type() const;
// Returns the space that needs to be collected for RetryAfterGC failures.
inline AllocationSpace allocation_space() const;
inline bool IsInternalError() const;
inline bool IsOutOfMemoryException() const;
static inline Failure* RetryAfterGC(AllocationSpace space);
static inline Failure* RetryAfterGC(); // NEW_SPACE
static inline Failure* Exception();
static inline Failure* InternalError();
static inline Failure* OutOfMemoryException();
// Casting.
static inline Failure* cast(MaybeObject* object);
// Dispatched behavior.
inline void FailurePrint() {
FailurePrint(stdout);
}
void FailurePrint(FILE* out);
void FailurePrint(StringStream* accumulator);
DECLARE_VERIFIER(Failure)
private:
inline intptr_t value() const;
static inline Failure* Construct(Type type, intptr_t value = 0);
DISALLOW_IMPLICIT_CONSTRUCTORS(Failure);
};
// Heap objects typically have a map pointer in their first word. However,
// during GC other data (e.g. mark bits, forwarding addresses) is sometimes
// encoded in the first word. The class MapWord is an abstraction of the
// value in a heap object's first word.
class MapWord BASE_EMBEDDED {
public:
// Normal state: the map word contains a map pointer.
// Create a map word from a map pointer.
static inline MapWord FromMap(Map* map);
// View this map word as a map pointer.
inline Map* ToMap();
// Scavenge collection: the map word of live objects in the from space
// contains a forwarding address (a heap object pointer in the to space).
// True if this map word is a forwarding address for a scavenge
// collection. Only valid during a scavenge collection (specifically,
// when all map words are heap object pointers, i.e. not during a full GC).
inline bool IsForwardingAddress();
// Create a map word from a forwarding address.
static inline MapWord FromForwardingAddress(HeapObject* object);
// View this map word as a forwarding address.
inline HeapObject* ToForwardingAddress();
static inline MapWord FromRawValue(uintptr_t value) {
return MapWord(value);
}
inline uintptr_t ToRawValue() {
return value_;
}
private:
// HeapObject calls the private constructor and directly reads the value.
friend class HeapObject;
explicit MapWord(uintptr_t value) : value_(value) {}
uintptr_t value_;
};
// HeapObject is the superclass for all classes describing heap allocated
// objects.
class HeapObject: public Object {
public:
// [map]: Contains a map which contains the object's reflective
// information.
inline Map* map();
inline void set_map(Map* value);
// The no-write-barrier version. This is OK if the object is white and in
// new space, or if the value is an immortal immutable object, like the maps
// of primitive (non-JS) objects like strings, heap numbers etc.
inline void set_map_no_write_barrier(Map* value);
// During garbage collection, the map word of a heap object does not
// necessarily contain a map pointer.
inline MapWord map_word();
inline void set_map_word(MapWord map_word);
// The Heap the object was allocated in. Used also to access Isolate.
inline Heap* GetHeap();
// Convenience method to get current isolate. This method can be
// accessed only when its result is the same as
// Isolate::Current(), it ASSERTs this. See also comment for GetHeap.
inline Isolate* GetIsolate();
// Converts an address to a HeapObject pointer.
static inline HeapObject* FromAddress(Address address);
// Returns the address of this HeapObject.
inline Address address();
// Iterates over pointers contained in the object (including the Map)
void Iterate(ObjectVisitor* v);
// Iterates over all pointers contained in the object except the
// first map pointer. The object type is given in the first
// parameter. This function does not access the map pointer in the
// object, and so is safe to call while the map pointer is modified.
void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
// Returns the heap object's size in bytes
inline int Size();
// Given a heap object's map pointer, returns the heap size in bytes
// Useful when the map pointer field is used for other purposes.
// GC internal.
inline int SizeFromMap(Map* map);
// Returns the field at offset in obj, as a read/write Object* reference.
// Does no checking, and is safe to use during GC, while maps are invalid.
// Does not invoke write barrier, so should only be assigned to
// during marking GC.
static inline Object** RawField(HeapObject* obj, int offset);
// Casting.
static inline HeapObject* cast(Object* obj);
// Return the write barrier mode for this. Callers of this function
// must be able to present a reference to an AssertNoAllocation
// object as a sign that they are not going to use this function
// from code that allocates and thus invalidates the returned write
// barrier mode.
inline WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation&);
// Dispatched behavior.
void HeapObjectShortPrint(StringStream* accumulator);
#ifdef OBJECT_PRINT
inline void HeapObjectPrint() {
HeapObjectPrint(stdout);
}
void HeapObjectPrint(FILE* out);
void PrintHeader(FILE* out, const char* id);
#endif
DECLARE_VERIFIER(HeapObject)
#ifdef VERIFY_HEAP
inline void VerifyObjectField(int offset);
inline void VerifySmiField(int offset);
// Verify a pointer is a valid HeapObject pointer that points to object
// areas in the heap.
static void VerifyHeapPointer(Object* p);
#endif
// Layout description.
// First field in a heap object is map.
static const int kMapOffset = Object::kHeaderSize;
static const int kHeaderSize = kMapOffset + kPointerSize;
STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
protected:
// helpers for calling an ObjectVisitor to iterate over pointers in the
// half-open range [start, end) specified as integer offsets
inline void IteratePointers(ObjectVisitor* v, int start, int end);
// as above, for the single element at "offset"
inline void IteratePointer(ObjectVisitor* v, int offset);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
};
// This class describes a body of an object of a fixed size
// in which all pointer fields are located in the [start_offset, end_offset)
// interval.
template<int start_offset, int end_offset, int size>
class FixedBodyDescriptor {
public:
static const int kStartOffset = start_offset;
static const int kEndOffset = end_offset;
static const int kSize = size;
static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
template<typename StaticVisitor>
static inline void IterateBody(HeapObject* obj) {
StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset),
HeapObject::RawField(obj, end_offset));
}
};
// This class describes a body of an object of a variable size
// in which all pointer fields are located in the [start_offset, object_size)
// interval.
template<int start_offset>
class FlexibleBodyDescriptor {
public:
static const int kStartOffset = start_offset;
static inline void IterateBody(HeapObject* obj,
int object_size,
ObjectVisitor* v);
template<typename StaticVisitor>
static inline void IterateBody(HeapObject* obj, int object_size) {
StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset),
HeapObject::RawField(obj, object_size));
}
};
// The HeapNumber class describes heap allocated numbers that cannot be
// represented in a Smi (small integer)
class HeapNumber: public HeapObject {
public:
// [value]: number value.
inline double value();
inline void set_value(double value);
// Casting.
static inline HeapNumber* cast(Object* obj);
// Dispatched behavior.
Object* HeapNumberToBoolean();
inline void HeapNumberPrint() {
HeapNumberPrint(stdout);
}
void HeapNumberPrint(FILE* out);
void HeapNumberPrint(StringStream* accumulator);
DECLARE_VERIFIER(HeapNumber)
inline int get_exponent();
inline int get_sign();
// Layout description.
static const int kValueOffset = HeapObject::kHeaderSize;
// IEEE doubles are two 32 bit words. The first is just mantissa, the second
// is a mixture of sign, exponent and mantissa. Our current platforms are all
// little endian apart from non-EABI arm which is little endian with big
// endian floating point word ordering!
#ifndef BIG_ENDIAN_FLOATING_POINT
static const int kMantissaOffset = kValueOffset;
static const int kExponentOffset = kValueOffset + 4;
#else
static const int kMantissaOffset = kValueOffset + 4;
static const int kExponentOffset = kValueOffset;
#endif
static const int kSize = kValueOffset + kDoubleSize;
static const uint32_t kSignMask = 0x80000000u;
static const uint32_t kExponentMask = 0x7ff00000u;
static const uint32_t kMantissaMask = 0xfffffu;
static const int kMantissaBits = 52;
static const int kExponentBits = 11;
static const int kExponentBias = 1023;
static const int kExponentShift = 20;
static const int kMantissaBitsInTopWord = 20;
static const int kNonMantissaBitsInTopWord = 12;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
};
enum EnsureElementsMode {
DONT_ALLOW_DOUBLE_ELEMENTS,
ALLOW_COPIED_DOUBLE_ELEMENTS,
ALLOW_CONVERTED_DOUBLE_ELEMENTS
};
// Indicates whether a property should be set or (re)defined. Setting of a
// property causes attributes to remain unchanged, writability to be checked
// and callbacks to be called. Defining of a property causes attributes to
// be updated and callbacks to be overridden.
enum SetPropertyMode {
SET_PROPERTY,
DEFINE_PROPERTY
};
// Indicator for one component of an AccessorPair.
enum AccessorComponent {
ACCESSOR_GETTER,
ACCESSOR_SETTER
};
// JSReceiver includes types on which properties can be defined, i.e.,
// JSObject and JSProxy.
class JSReceiver: public HeapObject {
public:
enum DeleteMode {
NORMAL_DELETION,
STRICT_DELETION,
FORCE_DELETION
};
// A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
// a keyed store is of the form a[expression] = foo.
enum StoreFromKeyed {
MAY_BE_STORE_FROM_KEYED,
CERTAINLY_NOT_STORE_FROM_KEYED
};
// Internal properties (e.g. the hidden properties dictionary) might
// be added even though the receiver is non-extensible.
enum ExtensibilityCheck {
PERFORM_EXTENSIBILITY_CHECK,
OMIT_EXTENSIBILITY_CHECK
};
// Casting.
static inline JSReceiver* cast(Object* obj);
static Handle<Object> SetProperty(Handle<JSReceiver> object,
Handle<String> key,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
// Can cause GC.
MUST_USE_RESULT MaybeObject* SetProperty(
String* key,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED);
MUST_USE_RESULT MaybeObject* SetProperty(
LookupResult* result,
String* key,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED);
MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter,
Object* value);
MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
// Set the index'th array element.
// Can cause GC, or return failure if GC is required.
MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype);
// Tests for the fast common case for property enumeration.
bool IsSimpleEnum();
// Returns the class name ([[Class]] property in the specification).
String* class_name();
// Returns the constructor name (the name (possibly, inferred name) of the
// function that was used to instantiate the object).
String* constructor_name();
inline PropertyAttributes GetPropertyAttribute(String* name);
PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver* receiver,
String* name);
PropertyAttributes GetLocalPropertyAttribute(String* name);
// Can cause a GC.
inline bool HasProperty(String* name);
inline bool HasLocalProperty(String* name);
inline bool HasElement(uint32_t index);
// Return the object's prototype (might be Heap::null_value()).
inline Object* GetPrototype();
// Return the constructor function (may be Heap::null_value()).
inline Object* GetConstructor();
// Set the object's prototype (only JSReceiver and null are allowed).
MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
bool skip_hidden_prototypes);
// Retrieves a permanent object identity hash code. The undefined value might
// be returned in case no hash was created yet and OMIT_CREATION was used.
inline MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
// Lookup a property. If found, the result is valid and has
// detailed information.
void LocalLookup(String* name, LookupResult* result);
void Lookup(String* name, LookupResult* result);
protected:
Smi* GenerateIdentityHash();
private:
PropertyAttributes GetPropertyAttribute(JSReceiver* receiver,
LookupResult* result,
String* name,
bool continue_search);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
};
// The JSObject describes real heap allocated JavaScript objects with
// properties.
// Note that the map of JSObject changes during execution to enable inline
// caching.
class JSObject: public JSReceiver {
public:
// [properties]: Backing storage for properties.
// properties is a FixedArray in the fast case and a Dictionary in the
// slow case.
DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
inline void initialize_properties();
inline bool HasFastProperties();
inline StringDictionary* property_dictionary(); // Gets slow properties.
// [elements]: The elements (properties with names that are integers).
//
// Elements can be in two general modes: fast and slow. Each mode
// corrensponds to a set of object representations of elements that
// have something in common.
//
// In the fast mode elements is a FixedArray and so each element can
// be quickly accessed. This fact is used in the generated code. The
// elements array can have one of three maps in this mode:
// fixed_array_map, non_strict_arguments_elements_map or
// fixed_cow_array_map (for copy-on-write arrays). In the latter case
// the elements array may be shared by a few objects and so before
// writing to any element the array must be copied. Use
// EnsureWritableFastElements in this case.
//
// In the slow mode the elements is either a NumberDictionary, an
// ExternalArray, or a FixedArray parameter map for a (non-strict)
// arguments object.
DECL_ACCESSORS(elements, FixedArrayBase)
inline void initialize_elements();
MUST_USE_RESULT inline MaybeObject* ResetElements();
inline ElementsKind GetElementsKind();
inline ElementsAccessor* GetElementsAccessor();
// Returns true if an object has elements of FAST_SMI_ELEMENTS ElementsKind.
inline bool HasFastSmiElements();
// Returns true if an object has elements of FAST_ELEMENTS ElementsKind.
inline bool HasFastObjectElements();
// Returns true if an object has elements of FAST_ELEMENTS or
// FAST_SMI_ONLY_ELEMENTS.
inline bool HasFastSmiOrObjectElements();
// Returns true if an object has elements of FAST_DOUBLE_ELEMENTS
// ElementsKind.
inline bool HasFastDoubleElements();
// Returns true if an object has elements of FAST_HOLEY_*_ELEMENTS
// ElementsKind.
inline bool HasFastHoleyElements();
inline bool HasNonStrictArgumentsElements();
inline bool HasDictionaryElements();
inline bool HasExternalPixelElements();
inline bool HasExternalArrayElements();
inline bool HasExternalByteElements();
inline bool HasExternalUnsignedByteElements();
inline bool HasExternalShortElements();
inline bool HasExternalUnsignedShortElements();
inline bool HasExternalIntElements();
inline bool HasExternalUnsignedIntElements();
inline bool HasExternalFloatElements();
inline bool HasExternalDoubleElements();
bool HasFastArgumentsElements();
bool HasDictionaryArgumentsElements();
inline SeededNumberDictionary* element_dictionary(); // Gets slow elements.
inline void set_map_and_elements(
Map* map,
FixedArrayBase* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Requires: HasFastElements().
MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements();
// Collects elements starting at index 0.
// Undefined values are placed after non-undefined values.
// Returns the number of non-undefined values.
MUST_USE_RESULT MaybeObject* PrepareElementsForSort(uint32_t limit);
// As PrepareElementsForSort, but only on objects where elements is
// a dictionary, and it will stay a dictionary.
MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
Object* structure,
String* name);
// Can cause GC.
MUST_USE_RESULT MaybeObject* SetPropertyForResult(LookupResult* result,
String* key,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_mode);
MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
LookupResult* result,
String* name,
Object* value,
bool check_prototype,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(
Object* structure,
String* name,
Object* value,
JSObject* holder,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
ExtensibilityCheck extensibility_check);
static Handle<Object> SetLocalPropertyIgnoreAttributes(
Handle<JSObject> object,
Handle<String> key,
Handle<Object> value,
PropertyAttributes attributes);
// Try to follow an existing transition to a field with attributes NONE. The
// return value indicates whether the transition was successful.
static inline bool TryTransitionToField(Handle<JSObject> object,
Handle<String> key);
inline int LastAddedFieldIndex();
// Extend the receiver with a single fast property appeared first in the
// passed map. This also extends the property backing store if necessary.
static void AddFastPropertyUsingMap(Handle<JSObject> object, Handle<Map> map);
inline MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* map);
// Can cause GC.
MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
String* key,
Object* value,
PropertyAttributes attributes);
// Retrieve a value in a normalized object given a lookup result.
// Handles the special representation of JS global objects.
Object* GetNormalizedProperty(LookupResult* result);
// Sets the property value in a normalized object given a lookup result.
// Handles the special representation of JS global objects.
Object* SetNormalizedProperty(LookupResult* result, Object* value);
// Sets the property value in a normalized object given (key, value, details).
// Handles the special representation of JS global objects.
static Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
Handle<String> key,
Handle<Object> value,
PropertyDetails details);
MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
Object* value,
PropertyDetails details);
// Deletes the named property in a normalized object.
MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
DeleteMode mode);
MUST_USE_RESULT MaybeObject* OptimizeAsPrototype();
// Retrieve interceptors.
InterceptorInfo* GetNamedInterceptor();
InterceptorInfo* GetIndexedInterceptor();
// Used from JSReceiver.
PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
String* name,
bool continue_search);
PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
String* name,
bool continue_search);
PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
Object* receiver,
LookupResult* result,
String* name,
bool continue_search);
static void DefineAccessor(Handle<JSObject> object,
Handle<String> name,
Handle<Object> getter,
Handle<Object> setter,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
Object* getter,
Object* setter,
PropertyAttributes attributes);
// Try to define a single accessor paying attention to map transitions.
// Returns a JavaScript null if this was not possible and we have to use the
// slow case. Note that we can fail due to allocations, too.
MUST_USE_RESULT MaybeObject* DefineFastAccessor(
String* name,
AccessorComponent component,
Object* accessor,
PropertyAttributes attributes);
Object* LookupAccessor(String* name, AccessorComponent component);
MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
// Used from Object::GetProperty().
MUST_USE_RESULT MaybeObject* GetPropertyWithFailedAccessCheck(
Object* receiver,
LookupResult* result,
String* name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithInterceptor(
Object* receiver,
String* name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyPostInterceptor(
Object* receiver,
String* name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetLocalPropertyPostInterceptor(
Object* receiver,
String* name,
PropertyAttributes* attributes);
// Returns true if this is an instance of an api function and has
// been modified since it was created. May give false positives.
bool IsDirty();
// If the receiver is a JSGlobalProxy this method will return its prototype,
// otherwise the result is the receiver itself.
inline Object* BypassGlobalProxy();
// Accessors for hidden properties object.
//
// Hidden properties are not local properties of the object itself.
// Instead they are stored in an auxiliary structure kept as a local
// property with a special name Heap::hidden_symbol(). But if the
// receiver is a JSGlobalProxy then the auxiliary object is a property
// of its prototype, and if it's a detached proxy, then you can't have
// hidden properties.
// Sets a hidden property on this object. Returns this object if successful,
// undefined if called on a detached proxy.
static Handle<Object> SetHiddenProperty(Handle<JSObject> obj,
Handle<String> key,
Handle<Object> value);
// Returns a failure if a GC is required.
MUST_USE_RESULT MaybeObject* SetHiddenProperty(String* key, Object* value);
// Gets the value of a hidden property with the given key. Returns undefined
// if the property doesn't exist (or if called on a detached proxy),
// otherwise returns the value set for the key.
Object* GetHiddenProperty(String* key);
// Deletes a hidden property. Deleting a non-existing property is
// considered successful.
void DeleteHiddenProperty(String* key);
// Returns true if the object has a property with the hidden symbol as name.
bool HasHiddenProperties();
static int GetIdentityHash(Handle<JSObject> obj);
MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
MUST_USE_RESULT MaybeObject* SetIdentityHash(Smi* hash, CreationFlag flag);
static Handle<Object> DeleteProperty(Handle<JSObject> obj,
Handle<String> name);
MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
static Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
inline void ValidateElements();
// Makes sure that this object can contain HeapObject as elements.
MUST_USE_RESULT inline MaybeObject* EnsureCanContainHeapObjectElements();
// Makes sure that this object can contain the specified elements.
MUST_USE_RESULT inline MaybeObject* EnsureCanContainElements(
Object** elements,
uint32_t count,
EnsureElementsMode mode);
MUST_USE_RESULT inline MaybeObject* EnsureCanContainElements(
FixedArrayBase* elements,
uint32_t length,
EnsureElementsMode mode);
MUST_USE_RESULT MaybeObject* EnsureCanContainElements(
Arguments* arguments,
uint32_t first_arg,
uint32_t arg_count,
EnsureElementsMode mode);
// Do we want to keep the elements in fast case when increasing the
// capacity?
bool ShouldConvertToSlowElements(int new_capacity);
// Returns true if the backing storage for the slow-case elements of
// this object takes up nearly as much space as a fast-case backing
// storage would. In that case the JSObject should have fast
// elements.
bool ShouldConvertToFastElements();
// Returns true if the elements of JSObject contains only values that can be
// represented in a FixedDoubleArray and has at least one value that can only
// be represented as a double and not a Smi.
bool ShouldConvertToFastDoubleElements(bool* has_smi_only_elements);
// Tells whether the index'th element is present.
bool HasElementWithReceiver(JSReceiver* receiver, uint32_t index);
// Computes the new capacity when expanding the elements of a JSObject.
static int NewElementsCapacity(int old_capacity) {
// (old_capacity + 50%) + 16
return old_capacity + (old_capacity >> 1) + 16;
}
// Tells whether the index'th element is present and how it is stored.
enum LocalElementType {
// There is no element with given index.
UNDEFINED_ELEMENT,
// Element with given index is handled by interceptor.
INTERCEPTED_ELEMENT,
// Element with given index is character in string.
STRING_CHARACTER_ELEMENT,
// Element with given index is stored in fast backing store.
FAST_ELEMENT,
// Element with given index is stored in slow backing store.
DICTIONARY_ELEMENT
};
LocalElementType HasLocalElement(uint32_t index);
bool HasElementWithInterceptor(JSReceiver* receiver, uint32_t index);
MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
Object* value,
StrictModeFlag strict_mode,
bool check_prototype);
MUST_USE_RESULT MaybeObject* SetDictionaryElement(
uint32_t index,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype,
SetPropertyMode set_mode = SET_PROPERTY);
MUST_USE_RESULT MaybeObject* SetFastDoubleElement(
uint32_t index,
Object* value,
StrictModeFlag strict_mode,
bool check_prototype = true);
static Handle<Object> SetOwnElement(Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
StrictModeFlag strict_mode);
// Empty handle is returned if the element cannot be set to the given value.
static MUST_USE_RESULT Handle<Object> SetElement(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attr,
StrictModeFlag strict_mode,
SetPropertyMode set_mode = SET_PROPERTY);
// A Failure object is returned if GC is needed.
MUST_USE_RESULT MaybeObject* SetElement(
uint32_t index,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype = true,
SetPropertyMode set_mode = SET_PROPERTY);
// Returns the index'th element.
// The undefined object if index is out of bounds.
MUST_USE_RESULT MaybeObject* GetElementWithInterceptor(Object* receiver,
uint32_t index);
enum SetFastElementsCapacitySmiMode {
kAllowSmiElements,
kForceSmiElements,
kDontAllowSmiElements
};
// Replace the elements' backing store with fast elements of the given
// capacity. Update the length for JSArrays. Returns the new backing
// store.
MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(
int capacity,
int length,
SetFastElementsCapacitySmiMode smi_mode);
MUST_USE_RESULT MaybeObject* SetFastDoubleElementsCapacityAndLength(
int capacity,
int length);
// Lookup interceptors are used for handling properties controlled by host
// objects.
inline bool HasNamedInterceptor();
inline bool HasIndexedInterceptor();
// Support functions for v8 api (needed for correct interceptor behavior).
bool HasRealNamedProperty(String* key);
bool HasRealElementProperty(uint32_t index);
bool HasRealNamedCallbackProperty(String* key);
// Get the header size for a JSObject. Used to compute the index of
// internal fields as well as the number of internal fields.
inline int GetHeaderSize();
inline int GetInternalFieldCount();
inline int GetInternalFieldOffset(int index);
inline Object* GetInternalField(int index);
inline void SetInternalField(int index, Object* value);
inline void SetInternalField(int index, Smi* value);
// The following lookup functions skip interceptors.
void LocalLookupRealNamedProperty(String* name, LookupResult* result);
void LookupRealNamedProperty(String* name, LookupResult* result);
void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
void LookupCallbackProperty(String* name, LookupResult* result);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
int NumberOfLocalProperties(PropertyAttributes filter = NONE);
// Fill in details for properties into storage starting at the specified
// index.
void GetLocalPropertyNames(FixedArray* storage, int index);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
int NumberOfLocalElements(PropertyAttributes filter);
// Returns the number of enumerable elements (ignoring interceptors).
int NumberOfEnumElements();
// Returns the number of elements on this object filtering out elements
// with the specified attributes (ignoring interceptors).
int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
// Count and fill in the enumerable elements into storage.
// (storage->length() == NumberOfEnumElements()).
// If storage is NULL, will count the elements without adding
// them to any storage.
// Returns the number of enumerable elements.
int GetEnumElementKeys(FixedArray* storage);
// Add a property to a fast-case object using a map transition to
// new_map.
MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
String* name,
Object* value,
int field_index);
// Add a constant function property to a fast-case object.
// This leaves a CONSTANT_TRANSITION in the old map, and
// if it is called on a second object with this map, a
// normal property is added instead, with a map transition.
// This avoids the creation of many maps with the same constant
// function, all orphaned.
MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
String* name,
JSFunction* function,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
String* name,
Object* value,
PropertyAttributes attributes);
// Returns a new map with all transitions dropped from the object's current
// map and the ElementsKind set.
static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
ElementsKind to_kind);
inline MUST_USE_RESULT MaybeObject* GetElementsTransitionMap(
Isolate* isolate,
ElementsKind elements_kind);
MUST_USE_RESULT MaybeObject* GetElementsTransitionMapSlow(
ElementsKind elements_kind);
static Handle<Object> TransitionElementsKind(Handle<JSObject> object,
ElementsKind to_kind);
MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind);
// Replaces an existing transition with a transition to a map with a FIELD.
MUST_USE_RESULT MaybeObject* ConvertTransitionToMapTransition(
int transition_index,
String* name,
Object* new_value,
PropertyAttributes attributes);
// Converts a descriptor of any other type to a real field, backed by the
// properties array.
MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
String* name,
Object* new_value,
PropertyAttributes attributes);
// Add a property to a fast-case object.
MUST_USE_RESULT MaybeObject* AddFastProperty(
String* name,
Object* value,
PropertyAttributes attributes,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
// Add a property to a slow-case object.
MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
Object* value,
PropertyAttributes attributes);
// Add a property to an object.
MUST_USE_RESULT MaybeObject* AddProperty(
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED,
ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK);
// Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties
// added this number can be indicated to have the backing store allocated to
// an initial capacity for holding these properties.
static void NormalizeProperties(Handle<JSObject> object,
PropertyNormalizationMode mode,
int expected_additional_properties);
MUST_USE_RESULT MaybeObject* NormalizeProperties(
PropertyNormalizationMode mode,
int expected_additional_properties);
// Convert and update the elements backing store to be a
// SeededNumberDictionary dictionary. Returns the backing after conversion.
static Handle<SeededNumberDictionary> NormalizeElements(
Handle<JSObject> object);
MUST_USE_RESULT MaybeObject* NormalizeElements();
static void UpdateMapCodeCache(Handle<JSObject> object,
Handle<String> name,
Handle<Code> code);
MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
// Transform slow named properties to fast variants.
// Returns failure if allocation failed.
static void TransformToFastProperties(Handle<JSObject> object,
int unused_property_fields);
MUST_USE_RESULT MaybeObject* TransformToFastProperties(
int unused_property_fields);
// Access fast-case object properties at index.
inline Object* FastPropertyAt(int index);
inline Object* FastPropertyAtPut(int index, Object* value);
// Access to in object properties.
inline int GetInObjectPropertyOffset(int index);
inline Object* InObjectPropertyAt(int index);
inline Object* InObjectPropertyAtPut(int index,
Object* value,
WriteBarrierMode mode
= UPDATE_WRITE_BARRIER);
// Initializes the body after properties slot, properties slot is
// initialized by set_properties. Fill the pre-allocated fields with
// pre_allocated_value and the rest with filler_value.
// Note: this call does not update write barrier, the caller is responsible
// to ensure that |filler_value| can be collected without WB here.
inline void InitializeBody(Map* map,
Object* pre_allocated_value,
Object* filler_value);
// Check whether this object references another object
bool ReferencesObject(Object* obj);
// Casting.
static inline JSObject* cast(Object* obj);
// Disalow further properties to be added to the object.
static Handle<Object> PreventExtensions(Handle<JSObject> object);
MUST_USE_RESULT MaybeObject* PreventExtensions();
// Dispatched behavior.
void JSObjectShortPrint(StringStream* accumulator);
#ifdef OBJECT_PRINT
inline void JSObjectPrint() {
JSObjectPrint(stdout);
}
void JSObjectPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSObject)
#ifdef OBJECT_PRINT
inline void PrintProperties() {
PrintProperties(stdout);
}
void PrintProperties(FILE* out);
inline void PrintElements() {
PrintElements(stdout);
}
void PrintElements(FILE* out);
inline void PrintTransitions() {
PrintTransitions(stdout);
}
void PrintTransitions(FILE* out);
#endif
void PrintElementsTransition(
FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
ElementsKind to_kind, FixedArrayBase* to_elements);
#ifdef DEBUG
// Structure for collecting spill information about JSObjects.
class SpillInformation {
public:
void Clear();
void Print();
int number_of_objects_;
int number_of_objects_with_fast_properties_;
int number_of_objects_with_fast_elements_;
int number_of_fast_used_fields_;
int number_of_fast_unused_fields_;
int number_of_slow_used_properties_;
int number_of_slow_unused_properties_;
int number_of_fast_used_elements_;
int number_of_fast_unused_elements_;
int number_of_slow_used_elements_;
int number_of_slow_unused_elements_;
};
void IncrementSpillStatistics(SpillInformation* info);
#endif
Object* SlowReverseLookup(Object* value);
// Maximal number of fast properties for the JSObject. Used to
// restrict the number of map transitions to avoid an explosion in
// the number of maps for objects used as dictionaries.
inline bool TooManyFastProperties(int properties, StoreFromKeyed store_mode);
// Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
// Also maximal value of JSArray's length property.
static const uint32_t kMaxElementCount = 0xffffffffu;
// Constants for heuristics controlling conversion of fast elements
// to slow elements.
// Maximal gap that can be introduced by adding an element beyond
// the current elements length.
static const uint32_t kMaxGap = 1024;
// Maximal length of fast elements array that won't be checked for
// being dense enough on expansion.
static const int kMaxUncheckedFastElementsLength = 5000;
// Same as above but for old arrays. This limit is more strict. We
// don't want to be wasteful with long lived objects.
static const int kMaxUncheckedOldFastElementsLength = 500;
static const int kInitialMaxFastElementArray = 100000;
static const int kFastPropertiesSoftLimit = 12;
static const int kMaxFastProperties = 64;
static const int kMaxInstanceSize = 255 * kPointerSize;
// When extending the backing storage for property values, we increase
// its size by more than the 1 entry necessary, so sequentially adding fields
// to the same object requires fewer allocations and copies.
static const int kFieldsAdded = 3;
// Layout description.
static const int kPropertiesOffset = HeapObject::kHeaderSize;
static const int kElementsOffset = kPropertiesOffset + kPointerSize;
static const int kHeaderSize = kElementsOffset + kPointerSize;
STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
public:
static inline int SizeOf(Map* map, HeapObject* object);
};
private:
friend class DictionaryElementsAccessor;
MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
Object* structure,
uint32_t index,
Object* holder);
MUST_USE_RESULT MaybeObject* SetElementWithCallback(
Object* structure,
uint32_t index,
Object* value,
JSObject* holder,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
uint32_t index,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype,
SetPropertyMode set_mode);
MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
uint32_t index,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype,
SetPropertyMode set_mode);
// Searches the prototype chain for property 'name'. If it is found and
// has a setter, invoke it and set '*done' to true. If it is found and is
// read-only, reject and set '*done' to true. Otherwise, set '*done' to
// false. Can cause GC and can return a failure result with '*done==true'.
MUST_USE_RESULT MaybeObject* SetPropertyViaPrototypes(
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool* done);
MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
DeleteMode mode);
MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
MUST_USE_RESULT MaybeObject* DeleteFastElement(uint32_t index);
MUST_USE_RESULT MaybeObject* DeleteDictionaryElement(uint32_t index,
DeleteMode mode);
bool ReferencesObjectFromElements(FixedArray* elements,
ElementsKind kind,
Object* object);
// Returns true if most of the elements backing storage is used.
bool HasDenseElements();
// Gets the current elements capacity and the number of used elements.
void GetElementsCapacityAndUsage(int* capacity, int* used);
bool CanSetCallback(String* name);
MUST_USE_RESULT MaybeObject* SetElementCallback(
uint32_t index,
Object* structure,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* SetPropertyCallback(
String* name,
Object* structure,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* DefineElementAccessor(
uint32_t index,
Object* getter,
Object* setter,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* CreateAccessorPairFor(String* name);
MUST_USE_RESULT MaybeObject* DefinePropertyAccessor(
String* name,
Object* getter,
Object* setter,
PropertyAttributes attributes);
enum InitializeHiddenProperties {
CREATE_NEW_IF_ABSENT,
ONLY_RETURN_INLINE_VALUE
};
// If create_if_absent is true, return the hash table backing store
// for hidden properties. If there is no backing store, allocate one.
// If create_if_absent is false, return the hash table backing store
// or the inline stored identity hash, whatever is found.
MUST_USE_RESULT MaybeObject* GetHiddenPropertiesHashTable(
InitializeHiddenProperties init_option);
// Set the hidden property backing store to either a hash table or
// the inline-stored identity hash.
MUST_USE_RESULT MaybeObject* SetHiddenPropertiesHashTable(
Object* value);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
};
// Common superclass for FixedArrays that allow implementations to share
// common accessors and some code paths.
class FixedArrayBase: public HeapObject {
public:
// [length]: length of the array.
inline int length();
inline void set_length(int value);
inline static FixedArrayBase* cast(Object* object);
// Layout description.
// Length is smi tagged when it is stored.
static const int kLengthOffset = HeapObject::kHeaderSize;
static const int kHeaderSize = kLengthOffset + kPointerSize;
};
class FixedDoubleArray;
class IncrementalMarking;
// FixedArray describes fixed-sized arrays with element type Object*.
class FixedArray: public FixedArrayBase {
public:
// Setter and getter for elements.
inline Object* get(int index);
// Setter that uses write barrier.
inline void set(int index, Object* value);
inline bool is_the_hole(int index);
// Setter that doesn't need write barrier).
inline void set(int index, Smi* value);
// Setter with explicit barrier mode.
inline void set(int index, Object* value, WriteBarrierMode mode);
// Setters for frequently used oddballs located in old space.
inline void set_undefined(int index);
// TODO(isolates): duplicate.
inline void set_undefined(Heap* heap, int index);
inline void set_null(int index);
// TODO(isolates): duplicate.
inline void set_null(Heap* heap, int index);
inline void set_the_hole(int index);
// Setters with less debug checks for the GC to use.
inline void set_unchecked(int index, Smi* value);
inline void set_null_unchecked(Heap* heap, int index);
inline void set_unchecked(Heap* heap, int index, Object* value,
WriteBarrierMode mode);
// Gives access to raw memory which stores the array's data.
inline Object** data_start();
inline Object** GetFirstElementAddress();
inline bool ContainsOnlySmisOrHoles();
// Copy operations.
MUST_USE_RESULT inline MaybeObject* Copy();
MUST_USE_RESULT MaybeObject* CopySize(int new_length);
// Add the elements of a JSArray to this FixedArray.
MUST_USE_RESULT MaybeObject* AddKeysFromJSArray(JSArray* array);
// Compute the union of this and other.
MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other);
// Copy a sub array from the receiver to dest.
void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
// Garbage collection support.
static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
// Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); }
// Casting.
static inline FixedArray* cast(Object* obj);
// Maximal allowed size, in bytes, of a single FixedArray.
// Prevents overflowing size computations, as well as extreme memory
// consumption.
static const int kMaxSize = 128 * MB * kPointerSize;
// Maximally allowed length of a FixedArray.
static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void FixedArrayPrint() {
FixedArrayPrint(stdout);
}
void FixedArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(FixedArray)
#ifdef DEBUG
// Checks if two FixedArrays have identical contents.
bool IsEqualTo(FixedArray* other);
#endif
// Swap two elements in a pair of arrays. If this array and the
// numbers array are the same object, the elements are only swapped
// once.
void SwapPairs(FixedArray* numbers, int i, int j);
// Sort prefix of this array and the numbers array as pairs wrt. the
// numbers. If the numbers array and the this array are the same
// object, the prefix of this array is sorted.
void SortPairs(FixedArray* numbers, uint32_t len);
class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
public:
static inline int SizeOf(Map* map, HeapObject* object) {
return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
}
};
protected:
// Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis.
static inline void NoWriteBarrierSet(FixedArray* array,
int index,
Object* value);
// Set operation on FixedArray without incremental write barrier. Can
// only be used if the object is guaranteed to be white (whiteness witness
// is present).
static inline void NoIncrementalWriteBarrierSet(FixedArray* array,
int index,
Object* value);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
};
// FixedDoubleArray describes fixed-sized arrays with element type double.
class FixedDoubleArray: public FixedArrayBase {
public:
// Setter and getter for elements.
inline double get_scalar(int index);
inline int64_t get_representation(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, double value);
inline void set_the_hole(int index);
// Checking for the hole.
inline bool is_the_hole(int index);
// Copy operations
MUST_USE_RESULT inline MaybeObject* Copy();
// Garbage collection support.
inline static int SizeFor(int length) {
return kHeaderSize + length * kDoubleSize;
}
// Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); }
inline static bool is_the_hole_nan(double value);
inline static double hole_nan_as_double();
inline static double canonical_not_the_hole_nan_as_double();
// Casting.
static inline FixedDoubleArray* cast(Object* obj);
// Maximal allowed size, in bytes, of a single FixedDoubleArray.
// Prevents overflowing size computations, as well as extreme memory
// consumption.
static const int kMaxSize = 512 * MB;
// Maximally allowed length of a FixedArray.
static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void FixedDoubleArrayPrint() {
FixedDoubleArrayPrint(stdout);
}
void FixedDoubleArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(FixedDoubleArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
};
// DescriptorArrays are fixed arrays used to hold instance descriptors.
// The format of the these objects is:
// [0]: Number of descriptors
// [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array:
// [0]: pointer to fixed array with enum cache
// [1]: either Smi(0) or pointer to fixed array with indices
// [2]: first key
// [2 + number of descriptors * kDescriptorSize]: start of slack
class DescriptorArray: public FixedArray {
public:
// WhitenessWitness is used to prove that a descriptor array is white
// (unmarked), so incremental write barriers can be skipped because the
// marking invariant cannot be broken and slots pointing into evacuation
// candidates will be discovered when the object is scanned. A witness is
// always stack-allocated right after creating an array. By allocating a
// witness, incremental marking is globally disabled. The witness is then
// passed along wherever needed to statically prove that the array is known to
// be white.
class WhitenessWitness {
public:
inline explicit WhitenessWitness(FixedArray* array);
inline ~WhitenessWitness();
private:
IncrementalMarking* marking_;
};
// Returns true for both shared empty_descriptor_array and for smis, which the
// map uses to encode additional bit fields when the descriptor array is not
// yet used.
inline bool IsEmpty();
// Returns the number of descriptors in the array.
int number_of_descriptors() {
ASSERT(length() >= kFirstIndex || IsEmpty());
int len = length();
return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value();
}
int number_of_descriptors_storage() {
int len = length();
return len == 0 ? 0 : (len - kFirstIndex) / kDescriptorSize;
}
int NumberOfSlackDescriptors() {
return number_of_descriptors_storage() - number_of_descriptors();
}
inline void SetNumberOfDescriptors(int number_of_descriptors);
inline int number_of_entries() { return number_of_descriptors(); }
bool HasEnumCache() {
return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi();
}
void CopyEnumCacheFrom(DescriptorArray* array) {
set(kEnumCacheIndex, array->get(kEnumCacheIndex));
}
FixedArray* GetEnumCache() {
ASSERT(HasEnumCache());
FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex));
return FixedArray::cast(bridge->get(kEnumCacheBridgeCacheIndex));
}
bool HasEnumIndicesCache() {
if (IsEmpty()) return false;
Object* object = get(kEnumCacheIndex);
if (object->IsSmi()) return false;
FixedArray* bridge = FixedArray::cast(object);
return !bridge->get(kEnumCacheBridgeIndicesCacheIndex)->IsSmi();
}
FixedArray* GetEnumIndicesCache() {
ASSERT(HasEnumIndicesCache());
FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex));
return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex));
}
Object** GetEnumCacheSlot() {
ASSERT(HasEnumCache());
return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
kEnumCacheOffset);
}
void ClearEnumCache();
// Initialize or change the enum cache,
// using the supplied storage for the small "bridge".
void SetEnumCache(FixedArray* bridge_storage,
FixedArray* new_cache,
Object* new_index_cache);
// Accessors for fetching instance descriptor at descriptor number.
inline String* GetKey(int descriptor_number);
inline Object** GetKeySlot(int descriptor_number);
inline Object* GetValue(int descriptor_number);
inline Object** GetValueSlot(int descriptor_number);
inline PropertyDetails GetDetails(int descriptor_number);
inline PropertyType GetType(int descriptor_number);
inline int GetFieldIndex(int descriptor_number);
inline JSFunction* GetConstantFunction(int descriptor_number);
inline Object* GetCallbacksObject(int descriptor_number);
inline AccessorDescriptor* GetCallbacks(int descriptor_number);
inline String* GetSortedKey(int descriptor_number);
inline int GetSortedKeyIndex(int descriptor_number);
inline void SetSortedKey(int pointer, int descriptor_number);
// Accessor for complete descriptor.
inline void Get(int descriptor_number, Descriptor* desc);
inline void Set(int descriptor_number,
Descriptor* desc,
const WhitenessWitness&);
inline void Set(int descriptor_number, Descriptor* desc);
// Append automatically sets the enumeration index. This should only be used
// to add descriptors in bulk at the end, followed by sorting the descriptor
// array.
inline void Append(Descriptor* desc, const WhitenessWitness&);
inline void Append(Descriptor* desc);
// Transfer a complete descriptor from the src descriptor array to this
// descriptor array.
void CopyFrom(int dst_index,
DescriptorArray* src,
int src_index,
const WhitenessWitness&);
MUST_USE_RESULT MaybeObject* CopyUpTo(int enumeration_index);
// Sort the instance descriptors by the hash codes of their keys.
void Sort();
// Search the instance descriptors for given name.
INLINE(int Search(String* name, int number_of_own_descriptors));
// As the above, but uses DescriptorLookupCache and updates it when
// necessary.
INLINE(int SearchWithCache(String* name, Map* map));
// Allocates a DescriptorArray, but returns the singleton
// empty descriptor array object if number_of_descriptors is 0.
MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors,
int slack = 0);
// Casting.
static inline DescriptorArray* cast(Object* obj);
// Constant for denoting key was not found.
static const int kNotFound = -1;
static const int kDescriptorLengthIndex = 0;
static const int kEnumCacheIndex = 1;
static const int kFirstIndex = 2;
// The length of the "bridge" to the enum cache.
static const int kEnumCacheBridgeLength = 2;
static const int kEnumCacheBridgeCacheIndex = 0;
static const int kEnumCacheBridgeIndicesCacheIndex = 1;
// Layout description.
static const int kDescriptorLengthOffset = FixedArray::kHeaderSize;
static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize;
static const int kFirstOffset = kEnumCacheOffset + kPointerSize;
// Layout description for the bridge array.
static const int kEnumCacheBridgeCacheOffset = FixedArray::kHeaderSize;
// Layout of descriptor.
static const int kDescriptorKey = 0;
static const int kDescriptorDetails = 1;
static const int kDescriptorValue = 2;
static const int kDescriptorSize = 3;
#ifdef OBJECT_PRINT
// Print all the descriptors.
inline void PrintDescriptors() {
PrintDescriptors(stdout);
}
void PrintDescriptors(FILE* out);
#endif
#ifdef DEBUG
// Is the descriptor array sorted and without duplicates?
bool IsSortedNoDuplicates(int valid_descriptors = -1);
// Is the descriptor array consistent with the back pointers in targets?
bool IsConsistentWithBackPointers(Map* current_map);
// Are two DescriptorArrays equal?
bool IsEqualTo(DescriptorArray* other);
#endif
// The maximum number of descriptors we want in a descriptor array (should
// fit in a page).
static const int kMaxNumberOfDescriptors = 1024 + 512;
// Returns the fixed array length required to hold number_of_descriptors
// descriptors.
static int LengthFor(int number_of_descriptors) {
return ToKeyIndex(number_of_descriptors);
}
private:
// An entry in a DescriptorArray, represented as an (array, index) pair.
class Entry {
public:
inline explicit Entry(DescriptorArray* descs, int index) :
descs_(descs), index_(index) { }
inline PropertyType type() { return descs_->GetType(index_); }
inline Object* GetCallbackObject() { return descs_->GetValue(index_); }
private:
DescriptorArray* descs_;
int index_;
};
// Conversion from descriptor number to array indices.
static int ToKeyIndex(int descriptor_number) {
return kFirstIndex +
(descriptor_number * kDescriptorSize) +
kDescriptorKey;
}
static int ToDetailsIndex(int descriptor_number) {
return kFirstIndex +
(descriptor_number * kDescriptorSize) +
kDescriptorDetails;
}
static int ToValueIndex(int descriptor_number) {
return kFirstIndex +
(descriptor_number * kDescriptorSize) +
kDescriptorValue;
}
// Swap first and second descriptor.
inline void SwapSortedKeys(int first, int second);
DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
};
enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
template<SearchMode search_mode, typename T>
inline int LinearSearch(T* array, String* name, int len, int valid_entries);
template<SearchMode search_mode, typename T>
inline int Search(T* array, String* name, int valid_entries = 0);
// HashTable is a subclass of FixedArray that implements a hash table
// that uses open addressing and quadratic probing.
//
// In order for the quadratic probing to work, elements that have not
// yet been used and elements that have been deleted are
// distinguished. Probing continues when deleted elements are
// encountered and stops when unused elements are encountered.
//
// - Elements with key == undefined have not been used yet.
// - Elements with key == the_hole have been deleted.
//
// The hash table class is parameterized with a Shape and a Key.
// Shape must be a class with the following interface:
// class ExampleShape {
// public:
// // Tells whether key matches other.
// static bool IsMatch(Key key, Object* other);
// // Returns the hash value for key.
// static uint32_t Hash(Key key);
// // Returns the hash value for object.
// static uint32_t HashForObject(Key key, Object* object);
// // Convert key to an object.
// static inline Object* AsObject(Key key);
// // The prefix size indicates number of elements in the beginning
// // of the backing storage.
// static const int kPrefixSize = ..;
// // The Element size indicates number of elements per entry.
// static const int kEntrySize = ..;
// };
// The prefix size indicates an amount of memory in the
// beginning of the backing storage that can be used for non-element
// information by subclasses.
template<typename Key>
class BaseShape {
public:
static const bool UsesSeed = false;
static uint32_t Hash(Key key) { return 0; }
static uint32_t SeededHash(Key key, uint32_t seed) {
ASSERT(UsesSeed);
return Hash(key);
}
static uint32_t HashForObject(Key key, Object* object) { return 0; }
static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) {
ASSERT(UsesSeed);
return HashForObject(key, object);
}
};
template<typename Shape, typename Key>
class HashTable: public FixedArray {
public:
enum MinimumCapacity {
USE_DEFAULT_MINIMUM_CAPACITY,
USE_CUSTOM_MINIMUM_CAPACITY
};
// Wrapper methods
inline uint32_t Hash(Key key) {
if (Shape::UsesSeed) {
return Shape::SeededHash(key,
GetHeap()->HashSeed());
} else {
return Shape::Hash(key);
}
}
inline uint32_t HashForObject(Key key, Object* object) {
if (Shape::UsesSeed) {
return Shape::SeededHashForObject(key,
GetHeap()->HashSeed(), object);
} else {
return Shape::HashForObject(key, object);
}
}
// Returns the number of elements in the hash table.
int NumberOfElements() {
return Smi::cast(get(kNumberOfElementsIndex))->value();
}
// Returns the number of deleted elements in the hash table.
int NumberOfDeletedElements() {
return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
}
// Returns the capacity of the hash table.
int Capacity() {
return Smi::cast(get(kCapacityIndex))->value();
}
// ElementAdded should be called whenever an element is added to a
// hash table.
void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
// ElementRemoved should be called whenever an element is removed from
// a hash table.
void ElementRemoved() {
SetNumberOfElements(NumberOfElements() - 1);
SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
}
void ElementsRemoved(int n) {
SetNumberOfElements(NumberOfElements() - n);
SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
}
// Returns a new HashTable object. Might return Failure.
MUST_USE_RESULT static MaybeObject* Allocate(
int at_least_space_for,
MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY,
PretenureFlag pretenure = NOT_TENURED);
// Computes the required capacity for a table holding the given
// number of elements. May be more than HashTable::kMaxCapacity.
static int ComputeCapacity(int at_least_space_for);
// Returns the key at entry.
Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
// Tells whether k is a real key. The hole and undefined are not allowed
// as keys and can be used to indicate missing or deleted elements.
bool IsKey(Object* k) {
return !k->IsTheHole() && !k->IsUndefined();
}
// Garbage collection support.
void IteratePrefix(ObjectVisitor* visitor);
void IterateElements(ObjectVisitor* visitor);
// Casting.
static inline HashTable* cast(Object* obj);
// Compute the probe offset (quadratic probing).
INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
return (n + n * n) >> 1;
}
static const int kNumberOfElementsIndex = 0;
static const int kNumberOfDeletedElementsIndex = 1;
static const int kCapacityIndex = 2;
static const int kPrefixStartIndex = 3;
static const int kElementsStartIndex =
kPrefixStartIndex + Shape::kPrefixSize;
static const int kEntrySize = Shape::kEntrySize;
static const int kElementsStartOffset =
kHeaderSize + kElementsStartIndex * kPointerSize;
static const int kCapacityOffset =
kHeaderSize + kCapacityIndex * kPointerSize;
// Constant used for denoting a absent entry.
static const int kNotFound = -1;
// Maximal capacity of HashTable. Based on maximal length of underlying
// FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
// cannot overflow.
static const int kMaxCapacity =
(FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
// Find entry for key otherwise return kNotFound.
inline int FindEntry(Key key);
int FindEntry(Isolate* isolate, Key key);
protected:
// Find the entry at which to insert element with the given key that
// has the given hash value.
uint32_t FindInsertionEntry(uint32_t hash);
// Returns the index for an entry (of the key)
static inline int EntryToIndex(int entry) {
return (entry * kEntrySize) + kElementsStartIndex;
}
// Update the number of elements in the hash table.
void SetNumberOfElements(int nof) {
set(kNumberOfElementsIndex, Smi::FromInt(nof));
}
// Update the number of deleted elements in the hash table.
void SetNumberOfDeletedElements(int nod) {
set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
}
// Sets the capacity of the hash table.
void SetCapacity(int capacity) {
// To scale a computed hash code to fit within the hash table, we
// use bit-wise AND with a mask, so the capacity must be positive
// and non-zero.
ASSERT(capacity > 0);
ASSERT(capacity <= kMaxCapacity);
set(kCapacityIndex, Smi::FromInt(capacity));
}
// Returns probe entry.
static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
ASSERT(IsPowerOf2(size));
return (hash + GetProbeOffset(number)) & (size - 1);
}
inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
return hash & (size - 1);
}
inline static uint32_t NextProbe(
uint32_t last, uint32_t number, uint32_t size) {
return (last + number) & (size - 1);
}
// Rehashes this hash-table into the new table.
MUST_USE_RESULT MaybeObject* Rehash(HashTable* new_table, Key key);
// Attempt to shrink hash table after removal of key.
MUST_USE_RESULT MaybeObject* Shrink(Key key);
// Ensure enough space for n additional elements.
MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
};
// HashTableKey is an abstract superclass for virtual key behavior.
class HashTableKey {
public:
// Returns whether the other object matches this key.
virtual bool IsMatch(Object* other) = 0;
// Returns the hash value for this key.
virtual uint32_t Hash() = 0;
// Returns the hash value for object.
virtual uint32_t HashForObject(Object* key) = 0;
// Returns the key object for storing into the hash table.
// If allocations fails a failure object is returned.
MUST_USE_RESULT virtual MaybeObject* AsObject() = 0;
// Required.
virtual ~HashTableKey() {}
};
class SymbolTableShape : public BaseShape<HashTableKey*> {
public:
static inline bool IsMatch(HashTableKey* key, Object* value) {
return key->IsMatch(value);
}
static inline uint32_t Hash(HashTableKey* key) {
return key->Hash();
}
static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
return key->HashForObject(object);
}
MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
return key->AsObject();
}
static const int kPrefixSize = 0;
static const int kEntrySize = 1;
};
class SeqAsciiString;
// SymbolTable.
//
// No special elements in the prefix and the element size is 1
// because only the symbol itself (the key) needs to be stored.
class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
public:
// Find symbol in the symbol table. If it is not there yet, it is
// added. The return value is the symbol table which might have
// been enlarged. If the return value is not a failure, the symbol
// pointer *s is set to the symbol found.
MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str,
Object** s);
MUST_USE_RESULT MaybeObject* LookupSubStringAsciiSymbol(
Handle<SeqAsciiString> str,
int from,
int length,
Object** s);
MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
Object** s);
MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
// Looks up a symbol that is equal to the given string and returns
// true if it is found, assigning the symbol to the given output
// parameter.
bool LookupSymbolIfExists(String* str, String** symbol);
bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol);
// Casting.
static inline SymbolTable* cast(Object* obj);
private:
MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
template <bool seq_ascii> friend class JsonParser;
DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
};
class MapCacheShape : public BaseShape<HashTableKey*> {
public:
static inline bool IsMatch(HashTableKey* key, Object* value) {
return key->IsMatch(value);
}
static inline uint32_t Hash(HashTableKey* key) {
return key->Hash();
}
static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
return key->HashForObject(object);
}
MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
return key->AsObject();
}
static const int kPrefixSize = 0;
static const int kEntrySize = 2;
};
// MapCache.
//
// Maps keys that are a fixed array of symbols to a map.
// Used for canonicalize maps for object literals.
class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(FixedArray* key);
MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
static inline MapCache* cast(Object* obj);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
};
template <typename Shape, typename Key>
class Dictionary: public HashTable<Shape, Key> {
public:
static inline Dictionary<Shape, Key>* cast(Object* obj) {
return reinterpret_cast<Dictionary<Shape, Key>*>(obj);
}
// Returns the value at entry.
Object* ValueAt(int entry) {
return this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 1);
}
// Set the value for entry.
void ValueAtPut(int entry, Object* value) {
this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 1, value);
}
// Returns the property details for the property at entry.
PropertyDetails DetailsAt(int entry) {
ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
return PropertyDetails(
Smi::cast(this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
}
// Set the details for entry.
void DetailsAtPut(int entry, PropertyDetails value) {
this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
}
// Sorting support
void CopyValuesTo(FixedArray* elements);
// Delete a property from the dictionary.
Object* DeleteProperty(int entry, JSObject::DeleteMode mode);
// Attempt to shrink the dictionary after deletion of key.
MUST_USE_RESULT MaybeObject* Shrink(Key key);
// Returns the number of elements in the dictionary filtering out properties
// with the specified attributes.
int NumberOfElementsFilterAttributes(PropertyAttributes filter);
// Returns the number of enumerable elements in the dictionary.
int NumberOfEnumElements();
enum SortMode { UNSORTED, SORTED };
// Copies keys to preallocated fixed array.
void CopyKeysTo(FixedArray* storage,
PropertyAttributes filter,
SortMode sort_mode);
// Fill in details for properties into storage.
void CopyKeysTo(FixedArray* storage, int index, SortMode sort_mode);
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
ASSERT(index != 0);
this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
}
int NextEnumerationIndex() {
return Smi::cast(FixedArray::get(kNextEnumerationIndexIndex))->value();
}
// Returns a new array for dictionary usage. Might return Failure.
MUST_USE_RESULT static MaybeObject* Allocate(int at_least_space_for);
// Ensure enough space for n additional elements.
MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
#ifdef OBJECT_PRINT
inline void Print() {
Print(stdout);
}
void Print(FILE* out);
#endif
// Returns the key (slow).
Object* SlowReverseLookup(Object* value);
// Sets the entry to (key, value) pair.
inline void SetEntry(int entry,
Object* key,
Object* value);
inline void SetEntry(int entry,
Object* key,
Object* value,
PropertyDetails details);
MUST_USE_RESULT MaybeObject* Add(Key key,
Object* value,
PropertyDetails details);
protected:
// Generic at put operation.
MUST_USE_RESULT MaybeObject* AtPut(Key key, Object* value);
// Add entry to dictionary.
MUST_USE_RESULT MaybeObject* AddEntry(Key key,
Object* value,
PropertyDetails details,
uint32_t hash);
// Generate new enumeration indices to avoid enumeration index overflow.
MUST_USE_RESULT MaybeObject* GenerateNewEnumerationIndices();
static const int kMaxNumberKeyIndex =
HashTable<Shape, Key>::kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
};
class StringDictionaryShape : public BaseShape<String*> {
public:
static inline bool IsMatch(String* key, Object* other);
static inline uint32_t Hash(String* key);
static inline uint32_t HashForObject(String* key, Object* object);
MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
static const int kPrefixSize = 2;
static const int kEntrySize = 3;
static const bool kIsEnumerable = true;
};
class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
public:
static inline StringDictionary* cast(Object* obj) {
ASSERT(obj->IsDictionary());
return reinterpret_cast<StringDictionary*>(obj);
}
// Copies enumerable keys to preallocated fixed array.
FixedArray* CopyEnumKeysTo(FixedArray* storage);
static void DoGenerateNewEnumerationIndices(
Handle<StringDictionary> dictionary);
// For transforming properties of a JSObject.
MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
JSObject* obj,
int unused_property_fields);
// Find entry for key, otherwise return kNotFound. Optimized version of
// HashTable::FindEntry.
int FindEntry(String* key);
};
class NumberDictionaryShape : public BaseShape<uint32_t> {
public:
static inline bool IsMatch(uint32_t key, Object* other);
MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key);
static const int kEntrySize = 3;
static const bool kIsEnumerable = false;
};
class SeededNumberDictionaryShape : public NumberDictionaryShape {
public:
static const bool UsesSeed = true;
static const int kPrefixSize = 2;
static inline uint32_t SeededHash(uint32_t key, uint32_t seed);
static inline uint32_t SeededHashForObject(uint32_t key,
uint32_t seed,
Object* object);
};
class UnseededNumberDictionaryShape : public NumberDictionaryShape {
public:
static const int kPrefixSize = 0;
static inline uint32_t Hash(uint32_t key);
static inline uint32_t HashForObject(uint32_t key, Object* object);
};
class SeededNumberDictionary
: public Dictionary<SeededNumberDictionaryShape, uint32_t> {
public:
static SeededNumberDictionary* cast(Object* obj) {
ASSERT(obj->IsDictionary());
return reinterpret_cast<SeededNumberDictionary*>(obj);
}
// Type specific at put (default NONE attributes is used when adding).
MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key,
Object* value,
PropertyDetails details);
// Set an existing entry or add a new one if needed.
// Return the updated dictionary.
MUST_USE_RESULT static Handle<SeededNumberDictionary> Set(
Handle<SeededNumberDictionary> dictionary,
uint32_t index,
Handle<Object> value,
PropertyDetails details);
MUST_USE_RESULT MaybeObject* Set(uint32_t key,
Object* value,
PropertyDetails details);
void UpdateMaxNumberKey(uint32_t key);
// If slow elements are required we will never go back to fast-case
// for the elements kept in this dictionary. We require slow
// elements if an element has been added at an index larger than
// kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
// when defining a getter or setter with a number key.
inline bool requires_slow_elements();
inline void set_requires_slow_elements();
// Get the value of the max number key that has been added to this
// dictionary. max_number_key can only be called if
// requires_slow_elements returns false.
inline uint32_t max_number_key();
// Bit masks.
static const int kRequiresSlowElementsMask = 1;
static const int kRequiresSlowElementsTagSize = 1;
static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
};
class UnseededNumberDictionary
: public Dictionary<UnseededNumberDictionaryShape, uint32_t> {
public:
static UnseededNumberDictionary* cast(Object* obj) {
ASSERT(obj->IsDictionary());
return reinterpret_cast<UnseededNumberDictionary*>(obj);
}
// Type specific at put (default NONE attributes is used when adding).
MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key, Object* value);
// Set an existing entry or add a new one if needed.
// Return the updated dictionary.
MUST_USE_RESULT static Handle<UnseededNumberDictionary> Set(
Handle<UnseededNumberDictionary> dictionary,
uint32_t index,
Handle<Object> value);
MUST_USE_RESULT MaybeObject* Set(uint32_t key, Object* value);
};
template <int entrysize>
class ObjectHashTableShape : public BaseShape<Object*> {
public:
static inline bool IsMatch(Object* key, Object* other);
static inline uint32_t Hash(Object* key);
static inline uint32_t HashForObject(Object* key, Object* object);
MUST_USE_RESULT static inline MaybeObject* AsObject(Object* key);
static const int kPrefixSize = 0;
static const int kEntrySize = entrysize;
};
// ObjectHashSet holds keys that are arbitrary objects by using the identity
// hash of the key for hashing purposes.
class ObjectHashSet: public HashTable<ObjectHashTableShape<1>, Object*> {
public:
static inline ObjectHashSet* cast(Object* obj) {
ASSERT(obj->IsHashTable());
return reinterpret_cast<ObjectHashSet*>(obj);
}
// Looks up whether the given key is part of this hash set.
bool Contains(Object* key);
// Adds the given key to this hash set.
MUST_USE_RESULT MaybeObject* Add(Object* key);
// Removes the given key from this hash set.
MUST_USE_RESULT MaybeObject* Remove(Object* key);
};
// ObjectHashTable maps keys that are arbitrary objects to object values by
// using the identity hash of the key for hashing purposes.
class ObjectHashTable: public HashTable<ObjectHashTableShape<2>, Object*> {
public:
static inline ObjectHashTable* cast(Object* obj) {
ASSERT(obj->IsHashTable());
return reinterpret_cast<ObjectHashTable*>(obj);
}
// Looks up the value associated with the given key. The hole value is
// returned in case the key is not present.
Object* Lookup(Object* key);
// Adds (or overwrites) the value associated with the given key. Mapping a
// key to the hole value causes removal of the whole entry.
MUST_USE_RESULT MaybeObject* Put(Object* key, Object* value);
private:
friend class MarkCompactCollector;
void AddEntry(int entry, Object* key, Object* value);
void RemoveEntry(int entry);
// Returns the index to the value of an entry.
static inline int EntryToValueIndex(int entry) {
return EntryToIndex(entry) + 1;
}
};
// JSFunctionResultCache caches results of some JSFunction invocation.
// It is a fixed array with fixed structure:
// [0]: factory function
// [1]: finger index
// [2]: current cache size
// [3]: dummy field.
// The rest of array are key/value pairs.
class JSFunctionResultCache: public FixedArray {
public:
static const int kFactoryIndex = 0;
static const int kFingerIndex = kFactoryIndex + 1;
static const int kCacheSizeIndex = kFingerIndex + 1;
static const int kDummyIndex = kCacheSizeIndex + 1;
static const int kEntriesIndex = kDummyIndex + 1;
static const int kEntrySize = 2; // key + value
static const int kFactoryOffset = kHeaderSize;
static const int kFingerOffset = kFactoryOffset + kPointerSize;
static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
inline void MakeZeroSize();
inline void Clear();
inline int size();
inline void set_size(int size);
inline int finger_index();
inline void set_finger_index(int finger_index);
// Casting
static inline JSFunctionResultCache* cast(Object* obj);
DECLARE_VERIFIER(JSFunctionResultCache)
};
// ScopeInfo represents information about different scopes of a source
// program and the allocation of the scope's variables. Scope information
// is stored in a compressed form in ScopeInfo objects and is used
// at runtime (stack dumps, deoptimization, etc.).
// This object provides quick access to scope info details for runtime
// routines.
class ScopeInfo : public FixedArray {
public:
static inline ScopeInfo* cast(Object* object);
// Return the type of this scope.
ScopeType Type();
// Does this scope call eval?
bool CallsEval();
// Return the language mode of this scope.
LanguageMode language_mode();
// Does this scope make a non-strict eval call?
bool CallsNonStrictEval() {
return CallsEval() && (language_mode() == CLASSIC_MODE);
}
// Return the total number of locals allocated on the stack and in the
// context. This includes the parameters that are allocated in the context.
int LocalCount();
// Return the number of stack slots for code. This number consists of two
// parts:
// 1. One stack slot per stack allocated local.
// 2. One stack slot for the function name if it is stack allocated.
int StackSlotCount();
// Return the number of context slots for code if a context is allocated. This
// number consists of three parts:
// 1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS
// 2. One context slot per context allocated local.
// 3. One context slot for the function name if it is context allocated.
// Parameters allocated in the context count as context allocated locals. If
// no contexts are allocated for this scope ContextLength returns 0.
int ContextLength();
// Is this scope the scope of a named function expression?
bool HasFunctionName();
// Return if this has context allocated locals.
bool HasHeapAllocatedLocals();
// Return if contexts are allocated for this scope.
bool HasContext();
// Return the function_name if present.
String* FunctionName();
// Return the name of the given parameter.
String* ParameterName(int var);
// Return the name of the given local.
String* LocalName(int var);
// Return the name of the given stack local.
String* StackLocalName(int var);
// Return the name of the given context local.
String* ContextLocalName(int var);
// Return the mode of the given context local.
VariableMode ContextLocalMode(int var);
// Return the initialization flag of the given context local.
InitializationFlag ContextLocalInitFlag(int var);
// Lookup support for serialized scope info. Returns the
// the stack slot index for a given slot name if the slot is
// present; otherwise returns a value < 0. The name must be a symbol
// (canonicalized).
int StackSlotIndex(String* name);
// Lookup support for serialized scope info. Returns the
// context slot index for a given slot name if the slot is present; otherwise
// returns a value < 0. The name must be a symbol (canonicalized).
// If the slot is present and mode != NULL, sets *mode to the corresponding
// mode for that variable.
int ContextSlotIndex(String* name,
VariableMode* mode,
InitializationFlag* init_flag);
// Lookup support for serialized scope info. Returns the
// parameter index for a given parameter name if the parameter is present;
// otherwise returns a value < 0. The name must be a symbol (canonicalized).
int ParameterIndex(String* name);
// Lookup support for serialized scope info. Returns the function context
// slot index if the function name is present and context-allocated (named
// function expressions, only), otherwise returns a value < 0. The name
// must be a symbol (canonicalized).
int FunctionContextSlotIndex(String* name, VariableMode* mode);
static Handle<ScopeInfo> Create(Scope* scope, Zone* zone);
// Serializes empty scope info.
static ScopeInfo* Empty();
#ifdef DEBUG
void Print();
#endif
// The layout of the static part of a ScopeInfo is as follows. Each entry is
// numeric and occupies one array slot.
// 1. A set of properties of the scope
// 2. The number of parameters. This only applies to function scopes. For
// non-function scopes this is 0.
// 3. The number of non-parameter variables allocated on the stack.
// 4. The number of non-parameter and parameter variables allocated in the
// context.
#define FOR_EACH_NUMERIC_FIELD(V) \
V(Flags) \
V(ParameterCount) \
V(StackLocalCount) \
V(ContextLocalCount)
#define FIELD_ACCESSORS(name) \
void Set##name(int value) { \
set(k##name, Smi::FromInt(value)); \
} \
int name() { \
if (length() > 0) { \
return Smi::cast(get(k##name))->value(); \
} else { \
return 0; \
} \
}
FOR_EACH_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS
private:
enum {
#define DECL_INDEX(name) k##name,
FOR_EACH_NUMERIC_FIELD(DECL_INDEX)
#undef DECL_INDEX
#undef FOR_EACH_NUMERIC_FIELD
kVariablePartIndex
};
// The layout of the variable part of a ScopeInfo is as follows:
// 1. ParameterEntries:
// This part stores the names of the parameters for function scopes. One
// slot is used per parameter, so in total this part occupies
// ParameterCount() slots in the array. For other scopes than function
// scopes ParameterCount() is 0.
// 2. StackLocalEntries:
// Contains the names of local variables that are allocated on the stack,
// in increasing order of the stack slot index. One slot is used per stack
// local, so in total this part occupies StackLocalCount() slots in the
// array.
// 3. ContextLocalNameEntries:
// Contains the names of local variables and parameters that are allocated
// in the context. They are stored in increasing order of the context slot
// index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
// context local, so in total this part occupies ContextLocalCount() slots
// in the array.
// 4. ContextLocalInfoEntries:
// Contains the variable modes and initialization flags corresponding to
// the context locals in ContextLocalNameEntries. One slot is used per
// context local, so in total this part occupies ContextLocalCount()
// slots in the array.
// 5. FunctionNameEntryIndex:
// If the scope belongs to a named function expression this part contains
// information about the function variable. It always occupies two array
// slots: a. The name of the function variable.
// b. The context or stack slot index for the variable.
int ParameterEntriesIndex();
int StackLocalEntriesIndex();
int ContextLocalNameEntriesIndex();
int ContextLocalInfoEntriesIndex();
int FunctionNameEntryIndex();
// Location of the function variable for named function expressions.
enum FunctionVariableInfo {
NONE, // No function name present.
STACK, // Function
CONTEXT,
UNUSED
};
// Properties of scopes.
class TypeField: public BitField<ScopeType, 0, 3> {};
class CallsEvalField: public BitField<bool, 3, 1> {};
class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
class FunctionVariableField: public BitField<FunctionVariableInfo, 6, 2> {};
class FunctionVariableMode: public BitField<VariableMode, 8, 3> {};
// BitFields representing the encoded information for context locals in the
// ContextLocalInfoEntries part.
class ContextLocalMode: public BitField<VariableMode, 0, 3> {};
class ContextLocalInitFlag: public BitField<InitializationFlag, 3, 1> {};
};
// The cache for maps used by normalized (dictionary mode) objects.
// Such maps do not have property descriptors, so a typical program
// needs very limited number of distinct normalized maps.
class NormalizedMapCache: public FixedArray {
public:
static const int kEntries = 64;
MUST_USE_RESULT MaybeObject* Get(JSObject* object,
PropertyNormalizationMode mode);
void Clear();
// Casting
static inline NormalizedMapCache* cast(Object* obj);
DECLARE_VERIFIER(NormalizedMapCache)
};
// ByteArray represents fixed sized byte arrays. Used for the relocation info
// that is attached to code objects.
class ByteArray: public FixedArrayBase {
public:
inline int Size() { return RoundUp(length() + kHeaderSize, kPointerSize); }
// Setter and getter.
inline byte get(int index);
inline void set(int index, byte value);
// Treat contents as an int array.
inline int get_int(int index);
static int SizeFor(int length) {
return OBJECT_POINTER_ALIGN(kHeaderSize + length);
}
// We use byte arrays for free blocks in the heap. Given a desired size in
// bytes that is a multiple of the word size and big enough to hold a byte
// array, this function returns the number of elements a byte array should
// have.
static int LengthFor(int size_in_bytes) {
ASSERT(IsAligned(size_in_bytes, kPointerSize));
ASSERT(size_in_bytes >= kHeaderSize);
return size_in_bytes - kHeaderSize;
}
// Returns data start address.
inline Address GetDataStartAddress();
// Returns a pointer to the ByteArray object for a given data start address.
static inline ByteArray* FromDataStartAddress(Address address);
// Casting.
static inline ByteArray* cast(Object* obj);
// Dispatched behavior.
inline int ByteArraySize() {
return SizeFor(this->length());
}
#ifdef OBJECT_PRINT
inline void ByteArrayPrint() {
ByteArrayPrint(stdout);
}
void ByteArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ByteArray)
// Layout description.
static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
// Maximal memory consumption for a single ByteArray.
static const int kMaxSize = 512 * MB;
// Maximal length of a single ByteArray.
static const int kMaxLength = kMaxSize - kHeaderSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
};
// FreeSpace represents fixed sized areas of the heap that are not currently in
// use. Used by the heap and GC.
class FreeSpace: public HeapObject {
public:
// [size]: size of the free space including the header.
inline int size();
inline void set_size(int value);
inline int Size() { return size(); }
// Casting.
static inline FreeSpace* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void FreeSpacePrint() {
FreeSpacePrint(stdout);
}
void FreeSpacePrint(FILE* out);
#endif
DECLARE_VERIFIER(FreeSpace)
// Layout description.
// Size is smi tagged when it is stored.
static const int kSizeOffset = HeapObject::kHeaderSize;
static const int kHeaderSize = kSizeOffset + kPointerSize;
static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FreeSpace);
};
// An ExternalArray represents a fixed-size array of primitive values
// which live outside the JavaScript heap. Its subclasses are used to
// implement the CanvasArray types being defined in the WebGL
// specification. As of this writing the first public draft is not yet
// available, but Khronos members can access the draft at:
// https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
//
// The semantics of these arrays differ from CanvasPixelArray.
// Out-of-range values passed to the setter are converted via a C
// cast, not clamping. Out-of-range indices cause exceptions to be
// raised rather than being silently ignored.
class ExternalArray: public FixedArrayBase {
public:
inline bool is_the_hole(int index) { return false; }
// [external_pointer]: The pointer to the external memory area backing this
// external array.
DECL_ACCESSORS(external_pointer, void) // Pointer to the data store.
// Casting.
static inline ExternalArray* cast(Object* obj);
// Maximal acceptable length for an external array.
static const int kMaxLength = 0x3fffffff;
// ExternalArray headers are not quadword aligned.
static const int kExternalPointerOffset =
POINTER_SIZE_ALIGN(FixedArrayBase::kLengthOffset + kPointerSize);
static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
};
// A ExternalPixelArray represents a fixed-size byte array with special
// semantics used for implementing the CanvasPixelArray object. Please see the
// specification at:
// http://www.whatwg.org/specs/web-apps/current-work/
// multipage/the-canvas-element.html#canvaspixelarray
// In particular, write access clamps the value written to 0 or 255 if the
// value written is outside this range.
class ExternalPixelArray: public ExternalArray {
public:
inline uint8_t* external_pixel_pointer();
// Setter and getter.
inline uint8_t get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, uint8_t value);
// This accessor applies the correct conversion from Smi, HeapNumber and
// undefined and clamps the converted value between 0 and 255.
Object* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalPixelArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalPixelArrayPrint() {
ExternalPixelArrayPrint(stdout);
}
void ExternalPixelArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ExternalPixelArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalPixelArray);
};
class ExternalByteArray: public ExternalArray {
public:
// Setter and getter.
inline int8_t get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, int8_t value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalByteArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalByteArrayPrint() {
ExternalByteArrayPrint(stdout);
}
void ExternalByteArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ExternalByteArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalByteArray);
};
class ExternalUnsignedByteArray: public ExternalArray {
public:
// Setter and getter.
inline uint8_t get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, uint8_t value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalUnsignedByteArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalUnsignedByteArrayPrint() {
ExternalUnsignedByteArrayPrint(stdout);
}
void ExternalUnsignedByteArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ExternalUnsignedByteArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedByteArray);
};
class ExternalShortArray: public ExternalArray {
public:
// Setter and getter.
inline int16_t get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, int16_t value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalShortArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalShortArrayPrint() {
ExternalShortArrayPrint(stdout);
}
void ExternalShortArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ExternalShortArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalShortArray);
};
class ExternalUnsignedShortArray: public ExternalArray {
public:
// Setter and getter.
inline uint16_t get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, uint16_t value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalUnsignedShortArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalUnsignedShortArrayPrint() {
ExternalUnsignedShortArrayPrint(stdout);
}
void ExternalUnsignedShortArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ExternalUnsignedShortArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedShortArray);
};
class ExternalIntArray: public ExternalArray {
public:
// Setter and getter.
inline int32_t get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, int32_t value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalIntArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalIntArrayPrint() {
ExternalIntArrayPrint(stdout);
}
void ExternalIntArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ExternalIntArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalIntArray);
};
class ExternalUnsignedIntArray: public ExternalArray {
public:
// Setter and getter.
inline uint32_t get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, uint32_t value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalUnsignedIntArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalUnsignedIntArrayPrint() {
ExternalUnsignedIntArrayPrint(stdout);
}
void ExternalUnsignedIntArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ExternalUnsignedIntArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUnsignedIntArray);
};
class ExternalFloatArray: public ExternalArray {
public:
// Setter and getter.
inline float get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, float value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalFloatArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalFloatArrayPrint() {
ExternalFloatArrayPrint(stdout);
}
void ExternalFloatArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(ExternalFloatArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloatArray);
};
class ExternalDoubleArray: public ExternalArray {
public:
// Setter and getter.
inline double get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, double value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
// Casting.
static inline ExternalDoubleArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalDoubleArrayPrint() {
ExternalDoubleArrayPrint(stdout);
}
void ExternalDoubleArrayPrint(FILE* out);
#endif // OBJECT_PRINT
DECLARE_VERIFIER(ExternalDoubleArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalDoubleArray);
};
// DeoptimizationInputData is a fixed array used to hold the deoptimization
// data for code generated by the Hydrogen/Lithium compiler. It also
// contains information about functions that were inlined. If N different
// functions were inlined then first N elements of the literal array will
// contain these functions.
//
// It can be empty.
class DeoptimizationInputData: public FixedArray {
public:
// Layout description. Indices in the array.
static const int kTranslationByteArrayIndex = 0;
static const int kInlinedFunctionCountIndex = 1;
static const int kLiteralArrayIndex = 2;
static const int kOsrAstIdIndex = 3;
static const int kOsrPcOffsetIndex = 4;
static const int kFirstDeoptEntryIndex = 5;
// Offsets of deopt entry elements relative to the start of the entry.
static const int kAstIdRawOffset = 0;
static const int kTranslationIndexOffset = 1;
static const int kArgumentsStackHeightOffset = 2;
static const int kPcOffset = 3;
static const int kDeoptEntrySize = 4;
// Simple element accessors.
#define DEFINE_ELEMENT_ACCESSORS(name, type) \
type* name() { \
return type::cast(get(k##name##Index)); \
} \
void Set##name(type* value) { \
set(k##name##Index, value); \
}
DEFINE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
DEFINE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi)
DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
#undef DEFINE_ELEMENT_ACCESSORS
// Accessors for elements of the ith deoptimization entry.
#define DEFINE_ENTRY_ACCESSORS(name, type) \
type* name(int i) { \
return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
} \
void Set##name(int i, type* value) { \
set(IndexForEntry(i) + k##name##Offset, value); \
}
DEFINE_ENTRY_ACCESSORS(AstIdRaw, Smi)
DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
DEFINE_ENTRY_ACCESSORS(Pc, Smi)
#undef DEFINE_ENTRY_ACCESSORS
BailoutId AstId(int i) {
return BailoutId(AstIdRaw(i)->value());
}
void SetAstId(int i, BailoutId value) {
SetAstIdRaw(i, Smi::FromInt(value.ToInt()));
}
int DeoptCount() {
return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
}
// Allocates a DeoptimizationInputData.
MUST_USE_RESULT static MaybeObject* Allocate(int deopt_entry_count,
PretenureFlag pretenure);
// Casting.
static inline DeoptimizationInputData* cast(Object* obj);
#ifdef ENABLE_DISASSEMBLER
void DeoptimizationInputDataPrint(FILE* out);
#endif
private:
static int IndexForEntry(int i) {
return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
}
static int LengthFor(int entry_count) {
return IndexForEntry(entry_count);
}
};
// DeoptimizationOutputData is a fixed array used to hold the deoptimization
// data for code generated by the full compiler.
// The format of the these objects is
// [i * 2]: Ast ID for ith deoptimization.
// [i * 2 + 1]: PC and state of ith deoptimization
class DeoptimizationOutputData: public FixedArray {
public:
int DeoptPoints() { return length() / 2; }
BailoutId AstId(int index) {
return BailoutId(Smi::cast(get(index * 2))->value());
}
void SetAstId(int index, BailoutId id) {
set(index * 2, Smi::FromInt(id.ToInt()));
}
Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); }
void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); }
static int LengthOfFixedArray(int deopt_points) {
return deopt_points * 2;
}
// Allocates a DeoptimizationOutputData.
MUST_USE_RESULT static MaybeObject* Allocate(int number_of_deopt_points,
PretenureFlag pretenure);
// Casting.
static inline DeoptimizationOutputData* cast(Object* obj);
#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
void DeoptimizationOutputDataPrint(FILE* out);
#endif
};
// Forward declaration.
class JSGlobalPropertyCell;
// TypeFeedbackCells is a fixed array used to hold the association between
// cache cells and AST ids for code generated by the full compiler.
// The format of the these objects is
// [i * 2]: Global property cell of ith cache cell.
// [i * 2 + 1]: Ast ID for ith cache cell.
class TypeFeedbackCells: public FixedArray {
public:
int CellCount() { return length() / 2; }
static int LengthOfFixedArray(int cell_count) { return cell_count * 2; }
// Accessors for AST ids associated with cache values.
inline TypeFeedbackId AstId(int index);
inline void SetAstId(int index, TypeFeedbackId id);
// Accessors for global property cells holding the cache values.
inline JSGlobalPropertyCell* Cell(int index);
inline void SetCell(int index, JSGlobalPropertyCell* cell);
// The object that indicates an uninitialized cache.
static inline Handle<Object> UninitializedSentinel(Isolate* isolate);
// The object that indicates a megamorphic state.
static inline Handle<Object> MegamorphicSentinel(Isolate* isolate);
// A raw version of the uninitialized sentinel that's safe to read during
// garbage collection (e.g., for patching the cache).
static inline Object* RawUninitializedSentinel(Heap* heap);
// Casting.
static inline TypeFeedbackCells* cast(Object* obj);
static const int kForInFastCaseMarker = 0;
static const int kForInSlowCaseMarker = 1;
};
// Forward declaration.
class SafepointEntry;
class TypeFeedbackInfo;
// Code describes objects with on-the-fly generated machine code.
class Code: public HeapObject {
public:
// Opaque data type for encapsulating code flags like kind, inline
// cache state, and arguments count.
// FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
// enumeration type has correct value range (see Issue 830 for more details).
enum Flags {
FLAGS_MIN_VALUE = kMinInt,
FLAGS_MAX_VALUE = kMaxInt
};
#define CODE_KIND_LIST(V) \
V(FUNCTION) \
V(OPTIMIZED_FUNCTION) \
V(STUB) \
V(BUILTIN) \
V(LOAD_IC) \
V(KEYED_LOAD_IC) \
V(CALL_IC) \
V(KEYED_CALL_IC) \
V(STORE_IC) \
V(KEYED_STORE_IC) \
V(UNARY_OP_IC) \
V(BINARY_OP_IC) \
V(COMPARE_IC) \
V(TO_BOOLEAN_IC)
enum Kind {
#define DEFINE_CODE_KIND_ENUM(name) name,
CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
#undef DEFINE_CODE_KIND_ENUM
// Pseudo-kinds.
LAST_CODE_KIND = TO_BOOLEAN_IC,
REGEXP = BUILTIN,
FIRST_IC_KIND = LOAD_IC,
LAST_IC_KIND = TO_BOOLEAN_IC
};
// No more than 16 kinds. The value is currently encoded in four bits in
// Flags.
STATIC_ASSERT(LAST_CODE_KIND < 16);
// Types of stubs.
enum StubType {
NORMAL,
FIELD,
CONSTANT_FUNCTION,
CALLBACKS,
INTERCEPTOR,
MAP_TRANSITION,
NONEXISTENT
};
enum {
NUMBER_OF_KINDS = LAST_IC_KIND + 1
};
typedef int ExtraICState;
static const ExtraICState kNoExtraICState = 0;
#ifdef ENABLE_DISASSEMBLER
// Printing
static const char* Kind2String(Kind kind);
static const char* ICState2String(InlineCacheState state);
static const char* StubType2String(StubType type);
static void PrintExtraICState(FILE* out, Kind kind, ExtraICState extra);
inline void Disassemble(const char* name) {
Disassemble(name, stdout);
}
void Disassemble(const char* name, FILE* out);
#endif // ENABLE_DISASSEMBLER
// [instruction_size]: Size of the native instructions
inline int instruction_size();
inline void set_instruction_size(int value);
// [relocation_info]: Code relocation information
DECL_ACCESSORS(relocation_info, ByteArray)
void InvalidateRelocation();
// [handler_table]: Fixed array containing offsets of exception handlers.
DECL_ACCESSORS(handler_table, FixedArray)
// [deoptimization_data]: Array containing data for deopt.
DECL_ACCESSORS(deoptimization_data, FixedArray)
// [type_feedback_info]: Struct containing type feedback information.
// Will contain either a TypeFeedbackInfo object, or undefined.
DECL_ACCESSORS(type_feedback_info, Object)
// [gc_metadata]: Field used to hold GC related metadata. The contents of this
// field does not have to be traced during garbage collection since
// it is only used by the garbage collector itself.
DECL_ACCESSORS(gc_metadata, Object)
// [ic_age]: Inline caching age: the value of the Heap::global_ic_age
// at the moment when this object was created.
inline void set_ic_age(int count);
inline int ic_age();
// Unchecked accessors to be used during GC.
inline ByteArray* unchecked_relocation_info();
inline FixedArray* unchecked_deoptimization_data();
inline int relocation_size();
// [flags]: Various code flags.
inline Flags flags();
inline void set_flags(Flags flags);
// [flags]: Access to specific code flags.
inline Kind kind();
inline InlineCacheState ic_state(); // Only valid for IC stubs.
inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
inline StubType type(); // Only valid for monomorphic IC stubs.
inline int arguments_count(); // Only valid for call IC stubs.
// Testers for IC stub kinds.
inline bool is_inline_cache_stub();
inline bool is_load_stub() { return kind() == LOAD_IC; }
inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
inline bool is_store_stub() { return kind() == STORE_IC; }
inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
inline bool is_call_stub() { return kind() == CALL_IC; }
inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
inline bool is_unary_op_stub() { return kind() == UNARY_OP_IC; }
inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; }
inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
inline bool is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; }
// [major_key]: For kind STUB or BINARY_OP_IC, the major key.
inline int major_key();
inline void set_major_key(int value);
// For stubs, tells whether they should always exist, so that they can be
// called from other stubs.
inline bool is_pregenerated();
inline void set_is_pregenerated(bool value);
// [optimizable]: For FUNCTION kind, tells if it is optimizable.
inline bool optimizable();
inline void set_optimizable(bool value);
// [has_deoptimization_support]: For FUNCTION kind, tells if it has
// deoptimization support.
inline bool has_deoptimization_support();
inline void set_has_deoptimization_support(bool value);
// [has_debug_break_slots]: For FUNCTION kind, tells if it has
// been compiled with debug break slots.
inline bool has_debug_break_slots();
inline void set_has_debug_break_slots(bool value);
// [compiled_with_optimizing]: For FUNCTION kind, tells if it has
// been compiled with IsOptimizing set to true.
inline bool is_compiled_optimizable();
inline void set_compiled_optimizable(bool value);
// [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
// how long the function has been marked for OSR and therefore which
// level of loop nesting we are willing to do on-stack replacement
// for.
inline void set_allow_osr_at_loop_nesting_level(int level);
inline int allow_osr_at_loop_nesting_level();
// [profiler_ticks]: For FUNCTION kind, tells for how many profiler ticks
// the code object was seen on the stack with no IC patching going on.
inline int profiler_ticks();
inline void set_profiler_ticks(int ticks);
// [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots
// reserved in the code prologue.
inline unsigned stack_slots();
inline void set_stack_slots(unsigned slots);
// [safepoint_table_start]: For kind OPTIMIZED_CODE, the offset in
// the instruction stream where the safepoint table starts.
inline unsigned safepoint_table_offset();
inline void set_safepoint_table_offset(unsigned offset);
// [stack_check_table_start]: For kind FUNCTION, the offset in the
// instruction stream where the stack check table starts.
inline unsigned stack_check_table_offset();
inline void set_stack_check_table_offset(unsigned offset);
// [check type]: For kind CALL_IC, tells how to check if the
// receiver is valid for the given call.
inline CheckType check_type();
inline void set_check_type(CheckType value);
// [type-recording unary op type]: For kind UNARY_OP_IC.
inline byte unary_op_type();
inline void set_unary_op_type(byte value);
// [type-recording binary op type]: For kind BINARY_OP_IC.
inline byte binary_op_type();
inline void set_binary_op_type(byte value);
inline byte binary_op_result_type();
inline void set_binary_op_result_type(byte value);
// [compare state]: For kind COMPARE_IC, tells what state the stub is in.
inline byte compare_state();
inline void set_compare_state(byte value);
// [compare_operation]: For kind COMPARE_IC tells what compare operation the
// stub was generated for.
inline byte compare_operation();
inline void set_compare_operation(byte value);
// [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
inline byte to_boolean_state();
inline void set_to_boolean_state(byte value);
// [has_function_cache]: For kind STUB tells whether there is a function
// cache is passed to the stub.
inline bool has_function_cache();
inline void set_has_function_cache(bool flag);
bool allowed_in_shared_map_code_cache();
// Get the safepoint entry for the given pc.
SafepointEntry GetSafepointEntry(Address pc);
// Mark this code object as not having a stack check table. Assumes kind
// is FUNCTION.
void SetNoStackCheckTable();
// Find the first map in an IC stub.
Map* FindFirstMap();
class ExtraICStateStrictMode: public BitField<StrictModeFlag, 0, 1> {};
class ExtraICStateKeyedAccessGrowMode:
public BitField<KeyedAccessGrowMode, 1, 1> {}; // NOLINT
static const int kExtraICStateGrowModeShift = 1;
static inline StrictModeFlag GetStrictMode(ExtraICState extra_ic_state) {
return ExtraICStateStrictMode::decode(extra_ic_state);
}
static inline KeyedAccessGrowMode GetKeyedAccessGrowMode(
ExtraICState extra_ic_state) {
return ExtraICStateKeyedAccessGrowMode::decode(extra_ic_state);
}
static inline ExtraICState ComputeExtraICState(
KeyedAccessGrowMode grow_mode,
StrictModeFlag strict_mode) {
return ExtraICStateKeyedAccessGrowMode::encode(grow_mode) |
ExtraICStateStrictMode::encode(strict_mode);
}
// Flags operations.
static inline Flags ComputeFlags(
Kind kind,
InlineCacheState ic_state = UNINITIALIZED,
ExtraICState extra_ic_state = kNoExtraICState,
StubType type = NORMAL,
int argc = -1,
InlineCacheHolderFlag holder = OWN_MAP);
static inline Flags ComputeMonomorphicFlags(
Kind kind,
StubType type,
ExtraICState extra_ic_state = kNoExtraICState,
InlineCacheHolderFlag holder = OWN_MAP,
int argc = -1);
static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
static inline StubType ExtractTypeFromFlags(Flags flags);
static inline Kind ExtractKindFromFlags(Flags flags);
static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
static inline int ExtractArgumentsCountFromFlags(Flags flags);
static inline Flags RemoveTypeFromFlags(Flags flags);
// Convert a target address into a code object.
static inline Code* GetCodeFromTargetAddress(Address address);
// Convert an entry address into an object.
static inline Object* GetObjectFromEntryAddress(Address location_of_address);
// Returns the address of the first instruction.
inline byte* instruction_start();
// Returns the address right after the last instruction.
inline byte* instruction_end();
// Returns the size of the instructions, padding, and relocation information.
inline int body_size();
// Returns the address of the first relocation info (read backwards!).
inline byte* relocation_start();
// Code entry point.
inline byte* entry();
// Returns true if pc is inside this object's instructions.
inline bool contains(byte* pc);
// Relocate the code by delta bytes. Called to signal that this code
// object has been moved by delta bytes.
void Relocate(intptr_t delta);
// Migrate code described by desc.
void CopyFrom(const CodeDesc& desc);
// Returns the object size for a given body (used for allocation).
static int SizeFor(int body_size) {
ASSERT_SIZE_TAG_ALIGNED(body_size);
return RoundUp(kHeaderSize + body_size, kCodeAlignment);
}
// Calculate the size of the code object to report for log events. This takes
// the layout of the code object into account.
int ExecutableSize() {
// Check that the assumptions about the layout of the code object holds.
ASSERT_EQ(static_cast<int>(instruction_start() - address()),
Code::kHeaderSize);
return instruction_size() + Code::kHeaderSize;
}
// Locating source position.
int SourcePosition(Address pc);
int SourceStatementPosition(Address pc);
// Casting.
static inline Code* cast(Object* obj);
// Dispatched behavior.
int CodeSize() { return SizeFor(body_size()); }
inline void CodeIterateBody(ObjectVisitor* v);
template<typename StaticVisitor>
inline void CodeIterateBody(Heap* heap);
#ifdef OBJECT_PRINT
inline void CodePrint() {
CodePrint(stdout);
}
void CodePrint(FILE* out);
#endif
DECLARE_VERIFIER(Code)
void ClearInlineCaches();
void ClearTypeFeedbackCells(Heap* heap);
// Max loop nesting marker used to postpose OSR. We don't take loop
// nesting that is deeper than 5 levels into account.
static const int kMaxLoopNestingMarker = 6;
// Layout description.
static const int kInstructionSizeOffset = HeapObject::kHeaderSize;
static const int kRelocationInfoOffset = kInstructionSizeOffset + kIntSize;
static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize;
static const int kDeoptimizationDataOffset =
kHandlerTableOffset + kPointerSize;
static const int kTypeFeedbackInfoOffset =
kDeoptimizationDataOffset + kPointerSize;
static const int kGCMetadataOffset = kTypeFeedbackInfoOffset + kPointerSize;
static const int kICAgeOffset =
kGCMetadataOffset + kPointerSize;
static const int kFlagsOffset = kICAgeOffset + kIntSize;
static const int kKindSpecificFlags1Offset = kFlagsOffset + kIntSize;
static const int kKindSpecificFlags2Offset =
kKindSpecificFlags1Offset + kIntSize;
static const int kHeaderPaddingStart = kKindSpecificFlags2Offset + kIntSize;
// Add padding to align the instruction start following right after
// the Code object header.
static const int kHeaderSize =
(kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
// Byte offsets within kKindSpecificFlags1Offset.
static const int kOptimizableOffset = kKindSpecificFlags1Offset;
static const int kCheckTypeOffset = kKindSpecificFlags1Offset;
static const int kFullCodeFlags = kOptimizableOffset + 1;
class FullCodeFlagsHasDeoptimizationSupportField:
public BitField<bool, 0, 1> {}; // NOLINT
class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
static const int kAllowOSRAtLoopNestingLevelOffset = kFullCodeFlags + 1;
static const int kProfilerTicksOffset = kAllowOSRAtLoopNestingLevelOffset + 1;
// Flags layout. BitField<type, shift, size>.
class ICStateField: public BitField<InlineCacheState, 0, 3> {};
class TypeField: public BitField<StubType, 3, 3> {};
class CacheHolderField: public BitField<InlineCacheHolderFlag, 6, 1> {};
class KindField: public BitField<Kind, 7, 4> {};
class ExtraICStateField: public BitField<ExtraICState, 11, 2> {};
class IsPregeneratedField: public BitField<bool, 13, 1> {};
// KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION)
static const int kStackSlotsFirstBit = 0;
static const int kStackSlotsBitCount = 24;
static const int kUnaryOpTypeFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount;
static const int kUnaryOpTypeBitCount = 3;
static const int kBinaryOpTypeFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount;
static const int kBinaryOpTypeBitCount = 3;
static const int kBinaryOpResultTypeFirstBit =
kBinaryOpTypeFirstBit + kBinaryOpTypeBitCount;
static const int kBinaryOpResultTypeBitCount = 3;
static const int kCompareStateFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount;
static const int kCompareStateBitCount = 3;
static const int kCompareOperationFirstBit =
kCompareStateFirstBit + kCompareStateBitCount;
static const int kCompareOperationBitCount = 4;
static const int kToBooleanStateFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount;
static const int kToBooleanStateBitCount = 8;
static const int kHasFunctionCacheFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount;
static const int kHasFunctionCacheBitCount = 1;
STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32);
STATIC_ASSERT(kUnaryOpTypeFirstBit + kUnaryOpTypeBitCount <= 32);
STATIC_ASSERT(kBinaryOpTypeFirstBit + kBinaryOpTypeBitCount <= 32);
STATIC_ASSERT(kBinaryOpResultTypeFirstBit +
kBinaryOpResultTypeBitCount <= 32);
STATIC_ASSERT(kCompareStateFirstBit + kCompareStateBitCount <= 32);
STATIC_ASSERT(kCompareOperationFirstBit + kCompareOperationBitCount <= 32);
STATIC_ASSERT(kToBooleanStateFirstBit + kToBooleanStateBitCount <= 32);
STATIC_ASSERT(kHasFunctionCacheFirstBit + kHasFunctionCacheBitCount <= 32);
class StackSlotsField: public BitField<int,
kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT
class UnaryOpTypeField: public BitField<int,
kUnaryOpTypeFirstBit, kUnaryOpTypeBitCount> {}; // NOLINT
class BinaryOpTypeField: public BitField<int,
kBinaryOpTypeFirstBit, kBinaryOpTypeBitCount> {}; // NOLINT
class BinaryOpResultTypeField: public BitField<int,
kBinaryOpResultTypeFirstBit, kBinaryOpResultTypeBitCount> {}; // NOLINT
class CompareStateField: public BitField<int,
kCompareStateFirstBit, kCompareStateBitCount> {}; // NOLINT
class CompareOperationField: public BitField<int,
kCompareOperationFirstBit, kCompareOperationBitCount> {}; // NOLINT
class ToBooleanStateField: public BitField<int,
kToBooleanStateFirstBit, kToBooleanStateBitCount> {}; // NOLINT
class HasFunctionCacheField: public BitField<bool,
kHasFunctionCacheFirstBit, kHasFunctionCacheBitCount> {}; // NOLINT
// KindSpecificFlags2 layout (STUB and OPTIMIZED_FUNCTION)
static const int kStubMajorKeyFirstBit = 0;
static const int kSafepointTableOffsetFirstBit =
kStubMajorKeyFirstBit + kStubMajorKeyBits;
static const int kSafepointTableOffsetBitCount = 26;
STATIC_ASSERT(kStubMajorKeyFirstBit + kStubMajorKeyBits <= 32);
STATIC_ASSERT(kSafepointTableOffsetFirstBit +
kSafepointTableOffsetBitCount <= 32);
class SafepointTableOffsetField: public BitField<int,
kSafepointTableOffsetFirstBit,
kSafepointTableOffsetBitCount> {}; // NOLINT
class StubMajorKeyField: public BitField<int,
kStubMajorKeyFirstBit, kStubMajorKeyBits> {}; // NOLINT
// KindSpecificFlags2 layout (FUNCTION)
class StackCheckTableOffsetField: public BitField<int, 0, 31> {};
// Signed field cannot be encoded using the BitField class.
static const int kArgumentsCountShift = 14;
static const int kArgumentsCountMask = ~((1 << kArgumentsCountShift) - 1);
// This constant should be encodable in an ARM instruction.
static const int kFlagsNotUsedInLookup =
TypeField::kMask | CacheHolderField::kMask;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
};
// All heap objects have a Map that describes their structure.
// A Map contains information about:
// - Size information about the object
// - How to iterate over an object (for garbage collection)
class Map: public HeapObject {
public:
// Instance size.
// Size in bytes or kVariableSizeSentinel if instances do not have
// a fixed size.
inline int instance_size();
inline void set_instance_size(int value);
// Count of properties allocated in the object.
inline int inobject_properties();
inline void set_inobject_properties(int value);
// Count of property fields pre-allocated in the object when first allocated.
inline int pre_allocated_property_fields();
inline void set_pre_allocated_property_fields(int value);
// Instance type.
inline InstanceType instance_type();
inline void set_instance_type(InstanceType value);
// Tells how many unused property fields are available in the
// instance (only used for JSObject in fast mode).
inline int unused_property_fields();
inline void set_unused_property_fields(int value);
// Bit field.
inline byte bit_field();
inline void set_bit_field(byte value);
// Bit field 2.
inline byte bit_field2();
inline void set_bit_field2(byte value);
// Bit field 3.
inline int bit_field3();
inline void set_bit_field3(int value);
class EnumLengthBits: public BitField<int, 0, 11> {};
class NumberOfOwnDescriptorsBits: public BitField<int, 11, 11> {};
class IsShared: public BitField<bool, 22, 1> {};
class FunctionWithPrototype: public BitField<bool, 23, 1> {};
class DictionaryMap: public BitField<bool, 24, 1> {};
class OwnsDescriptors: public BitField<bool, 25, 1> {};
// Tells whether the object in the prototype property will be used
// for instances created from this function. If the prototype
// property is set to a value that is not a JSObject, the prototype
// property will not be used to create instances of the function.
// See ECMA-262, 13.2.2.
inline void set_non_instance_prototype(bool value);
inline bool has_non_instance_prototype();
// Tells whether function has special prototype property. If not, prototype
// property will not be created when accessed (will return undefined),
// and construction from this function will not be allowed.
inline void set_function_with_prototype(bool value);
inline bool function_with_prototype();
// Tells whether the instance with this map should be ignored by the
// __proto__ accessor.
inline void set_is_hidden_prototype() {
set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
}
inline bool is_hidden_prototype() {
return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
}
// Records and queries whether the instance has a named interceptor.
inline void set_has_named_interceptor() {
set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
}
inline bool has_named_interceptor() {
return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
}
// Records and queries whether the instance has an indexed interceptor.
inline void set_has_indexed_interceptor() {
set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
}
inline bool has_indexed_interceptor() {
return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
}
// Tells whether the instance is undetectable.
// An undetectable object is a special class of JSObject: 'typeof' operator
// returns undefined, ToBoolean returns false. Otherwise it behaves like
// a normal JS object. It is useful for implementing undetectable
// document.all in Firefox & Safari.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
inline void set_is_undetectable() {
set_bit_field(bit_field() | (1 << kIsUndetectable));
}
inline bool is_undetectable() {
return ((1 << kIsUndetectable) & bit_field()) != 0;
}
// Tells whether the instance has a call-as-function handler.
inline void set_has_instance_call_handler() {
set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
}
inline bool has_instance_call_handler() {
return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
}
inline void set_is_extensible(bool value);
inline bool is_extensible();
inline void set_elements_kind(ElementsKind elements_kind) {
ASSERT(elements_kind < kElementsKindCount);
ASSERT(kElementsKindCount <= (1 << kElementsKindBitCount));
set_bit_field2((bit_field2() & ~kElementsKindMask) |
(elements_kind << kElementsKindShift));
ASSERT(this->elements_kind() == elements_kind);
}
inline ElementsKind elements_kind() {
return static_cast<ElementsKind>(
(bit_field2() & kElementsKindMask) >> kElementsKindShift);
}
// Tells whether the instance has fast elements that are only Smis.
inline bool has_fast_smi_elements() {
return IsFastSmiElementsKind(elements_kind());
}
// Tells whether the instance has fast elements.
inline bool has_fast_object_elements() {
return IsFastObjectElementsKind(elements_kind());
}
inline bool has_fast_smi_or_object_elements() {
return IsFastSmiOrObjectElementsKind(elements_kind());
}
inline bool has_fast_double_elements() {
return IsFastDoubleElementsKind(elements_kind());
}
inline bool has_non_strict_arguments_elements() {
return elements_kind() == NON_STRICT_ARGUMENTS_ELEMENTS;
}
inline bool has_external_array_elements() {
return IsExternalArrayElementsKind(elements_kind());
}
inline bool has_dictionary_elements() {
return IsDictionaryElementsKind(elements_kind());
}
inline bool has_slow_elements_kind() {
return elements_kind() == DICTIONARY_ELEMENTS
|| elements_kind() == NON_STRICT_ARGUMENTS_ELEMENTS;
}
static bool IsValidElementsTransition(ElementsKind from_kind,
ElementsKind to_kind);
inline bool HasTransitionArray();
inline bool HasElementsTransition();
inline Map* elements_transition_map();
MUST_USE_RESULT inline MaybeObject* set_elements_transition_map(
Map* transitioned_map);
inline void SetTransition(int transition_index, Map* target);
inline Map* GetTransition(int transition_index);
MUST_USE_RESULT inline MaybeObject* AddTransition(String* key,
Map* target,
SimpleTransitionFlag flag);
DECL_ACCESSORS(transitions, TransitionArray)
inline void ClearTransitions(Heap* heap,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Tells whether the map is attached to SharedFunctionInfo
// (for inobject slack tracking).
inline void set_attached_to_shared_function_info(bool value);
inline bool attached_to_shared_function_info();
// Tells whether the map is shared between objects that may have different
// behavior. If true, the map should never be modified, instead a clone
// should be created and modified.
inline void set_is_shared(bool value);
inline bool is_shared();
// Tells whether the map is used for JSObjects in dictionary mode (ie
// normalized objects, ie objects for which HasFastProperties returns false).
// A map can never be used for both dictionary mode and fast mode JSObjects.
// False by default and for HeapObjects that are not JSObjects.
inline void set_dictionary_map(bool value);
inline bool is_dictionary_map();
// Tells whether the instance needs security checks when accessing its
// properties.
inline void set_is_access_check_needed(bool access_check_needed);
inline bool is_access_check_needed();
// [prototype]: implicit prototype object.
DECL_ACCESSORS(prototype, Object)
// [constructor]: points back to the function responsible for this map.
DECL_ACCESSORS(constructor, Object)
inline JSFunction* unchecked_constructor();
// [instance descriptors]: describes the object.
DECL_ACCESSORS(instance_descriptors, DescriptorArray)
inline void InitializeDescriptors(DescriptorArray* descriptors);
// [stub cache]: contains stubs compiled for this map.
DECL_ACCESSORS(code_cache, Object)
// [back pointer]: points back to the parent map from which a transition
// leads to this map. The field overlaps with prototype transitions and the
// back pointer will be moved into the prototype transitions array if
// required.
inline Object* GetBackPointer();
inline void SetBackPointer(Object* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void init_back_pointer(Object* undefined);
// [prototype transitions]: cache of prototype transitions.
// Prototype transition is a transition that happens
// when we change object's prototype to a new one.
// Cache format:
// 0: finger - index of the first free cell in the cache
// 1: back pointer that overlaps with prototype transitions field.
// 2 + 2 * i: prototype
// 3 + 2 * i: target map
inline FixedArray* GetPrototypeTransitions();
MUST_USE_RESULT inline MaybeObject* SetPrototypeTransitions(
FixedArray* prototype_transitions);
inline bool HasPrototypeTransitions();
inline HeapObject* UncheckedPrototypeTransitions();
inline TransitionArray* unchecked_transition_array();
static const int kProtoTransitionHeaderSize = 1;
static const int kProtoTransitionNumberOfEntriesOffset = 0;
static const int kProtoTransitionElementsPerEntry = 2;
static const int kProtoTransitionPrototypeOffset = 0;
static const int kProtoTransitionMapOffset = 1;
inline int NumberOfProtoTransitions() {
FixedArray* cache = GetPrototypeTransitions();
if (cache->length() == 0) return 0;
return
Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value();
}
inline void SetNumberOfProtoTransitions(int value) {
FixedArray* cache = GetPrototypeTransitions();
ASSERT(cache->length() != 0);
cache->set_unchecked(kProtoTransitionNumberOfEntriesOffset,
Smi::FromInt(value));
}
// Lookup in the map's instance descriptors and fill out the result
// with the given holder if the name is found. The holder may be
// NULL when this function is used from the compiler.
inline void LookupDescriptor(JSObject* holder,
String* name,
LookupResult* result);
inline void LookupTransition(JSObject* holder,
String* name,
LookupResult* result);
// The size of transition arrays are limited so they do not end up in large
// object space. Otherwise ClearNonLiveTransitions would leak memory while
// applying in-place right trimming.
inline bool CanHaveMoreTransitions();
int LastAdded() {
int number_of_own_descriptors = NumberOfOwnDescriptors();
ASSERT(number_of_own_descriptors > 0);
return number_of_own_descriptors - 1;
}
int NumberOfOwnDescriptors() {
return NumberOfOwnDescriptorsBits::decode(bit_field3());
}
void SetNumberOfOwnDescriptors(int number) {
ASSERT(number <= instance_descriptors()->number_of_descriptors());
set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
}
inline JSGlobalPropertyCell* RetrieveDescriptorsPointer();
int EnumLength() {
return EnumLengthBits::decode(bit_field3());
}
void SetEnumLength(int length) {
if (length != kInvalidEnumCache) {
ASSERT(length >= 0);
ASSERT(length == 0 || instance_descriptors()->HasEnumCache());
ASSERT(length <= NumberOfOwnDescriptors());
}
set_bit_field3(EnumLengthBits::update(bit_field3(), length));
}
inline bool owns_descriptors();
inline void set_owns_descriptors(bool is_shared);
MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
MUST_USE_RESULT MaybeObject* CopyWithPreallocatedFieldDescriptors();
MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
DescriptorArray* descriptors,
String* name,
TransitionFlag flag,
int descriptor_index);
MUST_USE_RESULT MaybeObject* ShareDescriptor(DescriptorArray* descriptors,
Descriptor* descriptor);
MUST_USE_RESULT MaybeObject* CopyAddDescriptor(Descriptor* descriptor,
TransitionFlag flag);
MUST_USE_RESULT MaybeObject* CopyInsertDescriptor(Descriptor* descriptor,
TransitionFlag flag);
MUST_USE_RESULT MaybeObject* CopyReplaceDescriptor(
DescriptorArray* descriptors,
Descriptor* descriptor,
int index,
TransitionFlag flag);
MUST_USE_RESULT MaybeObject* CopyAsElementsKind(ElementsKind kind,
TransitionFlag flag);
MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
NormalizedMapSharingMode sharing);
inline void AppendDescriptor(Descriptor* desc,
const DescriptorArray::WhitenessWitness&);
// Returns a copy of the map, with all transitions dropped from the
// instance descriptors.
MUST_USE_RESULT MaybeObject* Copy();
// Returns the property index for name (only valid for FAST MODE).
int PropertyIndexFor(String* name);
// Returns the next free property index (only valid for FAST MODE).
int NextFreePropertyIndex();
// Returns the number of properties described in instance_descriptors
// filtering out properties with the specified attributes.
int NumberOfDescribedProperties(DescriptorFlag which = OWN_DESCRIPTORS,
PropertyAttributes filter = NONE);
// Casting.
static inline Map* cast(Object* obj);
// Locate an accessor in the instance descriptor.
AccessorDescriptor* FindAccessor(String* name);
// Code cache operations.
// Clears the code cache.
inline void ClearCodeCache(Heap* heap);
// Update code cache.
static void UpdateCodeCache(Handle<Map> map,
Handle<String> name,
Handle<Code> code);
MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
// Extend the descriptor array of the map with the list of descriptors.
// In case of duplicates, the latest descriptor is used.
static void AppendCallbackDescriptors(Handle<Map> map,
Handle<Object> descriptors);
static void EnsureDescriptorSlack(Handle<Map> map, int slack);
// Returns the found code or undefined if absent.
Object* FindInCodeCache(String* name, Code::Flags flags);
// Returns the non-negative index of the code object if it is in the
// cache and -1 otherwise.
int IndexInCodeCache(Object* name, Code* code);
// Removes a code object from the code cache at the given index.
void RemoveFromCodeCache(String* name, Code* code, int index);
// Set all map transitions from this map to dead maps to null. Also clear
// back pointers in transition targets so that we do not process this map
// again while following back pointers.
void ClearNonLiveTransitions(Heap* heap);
// Computes a hash value for this map, to be used in HashTables and such.
int Hash();
// Compares this map to another to see if they describe equivalent objects.
// If |mode| is set to CLEAR_INOBJECT_PROPERTIES, |other| is treated as if
// it had exactly zero inobject properties.
// The "shared" flags of both this map and |other| are ignored.
bool EquivalentToForNormalization(Map* other, PropertyNormalizationMode mode);
// Returns the map that this map transitions to if its elements_kind
// is changed to |elements_kind|, or NULL if no such map is cached yet.
// |safe_to_add_transitions| is set to false if adding transitions is not
// allowed.
Map* LookupElementsTransitionMap(ElementsKind elements_kind);
// Returns the transitioned map for this map with the most generic
// elements_kind that's found in |candidates|, or null handle if no match is
// found at all.
Handle<Map> FindTransitionedMap(MapHandleList* candidates);
Map* FindTransitionedMap(MapList* candidates);
// Zaps the contents of backing data structures. Note that the
// heap verifier (i.e. VerifyMarkingVisitor) relies on zapping of objects
// holding weak references when incremental marking is used, because it also
// iterates over objects that are otherwise unreachable.
// In general we only want to call these functions in release mode when
// heap verification is turned on.
void ZapPrototypeTransitions();
void ZapTransitions();
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void MapPrint() {
MapPrint(stdout);
}
void MapPrint(FILE* out);
#endif
DECLARE_VERIFIER(Map)
#ifdef VERIFY_HEAP
void SharedMapVerify();
#endif
inline int visitor_id();
inline void set_visitor_id(int visitor_id);
typedef void (*TraverseCallback)(Map* map, void* data);
void TraverseTransitionTree(TraverseCallback callback, void* data);
// When you set the prototype of an object using the __proto__ accessor you
// need a new map for the object (the prototype is stored in the map). In
// order not to multiply maps unnecessarily we store these as transitions in
// the original map. That way we can transition to the same map if the same
// prototype is set, rather than creating a new map every time. The
// transitions are in the form of a map where the keys are prototype objects
// and the values are the maps the are transitioned to.
static const int kMaxCachedPrototypeTransitions = 256;
Map* GetPrototypeTransition(Object* prototype);
MUST_USE_RESULT MaybeObject* PutPrototypeTransition(Object* prototype,
Map* map);
static const int kMaxPreAllocatedPropertyFields = 255;
// Constant for denoting that the enum cache is not yet initialized.
static const int kInvalidEnumCache = EnumLengthBits::kMax;
// Layout description.
static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
// Storage for the transition array is overloaded to directly contain a back
// pointer if unused. When the map has transitions, the back pointer is
// transferred to the transition array and accessed through an extra
// indirection.
static const int kTransitionsOrBackPointerOffset =
kConstructorOffset + kPointerSize;
static const int kDescriptorsOffset =
kTransitionsOrBackPointerOffset + kPointerSize;
static const int kCodeCacheOffset =
kDescriptorsOffset + kPointerSize;
static const int kBitField3Offset = kCodeCacheOffset + kPointerSize;
static const int kSize = kBitField3Offset + kPointerSize;
// Layout of pointer fields. Heap iteration code relies on them
// being continuously allocated.
static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
static const int kPointerFieldsEndOffset = kBitField3Offset + kPointerSize;
// Byte offsets within kInstanceSizesOffset.
static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
static const int kInObjectPropertiesByte = 1;
static const int kInObjectPropertiesOffset =
kInstanceSizesOffset + kInObjectPropertiesByte;
static const int kPreAllocatedPropertyFieldsByte = 2;
static const int kPreAllocatedPropertyFieldsOffset =
kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
static const int kVisitorIdByte = 3;
static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
// Byte offsets within kInstanceAttributesOffset attributes.
static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
static const int kBitField2Offset = kInstanceAttributesOffset + 3;
STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
// Bit positions for bit field.
static const int kUnused = 0; // To be used for marking recently used maps.
static const int kHasNonInstancePrototype = 1;
static const int kIsHiddenPrototype = 2;
static const int kHasNamedInterceptor = 3;
static const int kHasIndexedInterceptor = 4;
static const int kIsUndetectable = 5;
static const int kHasInstanceCallHandler = 6;
static const int kIsAccessCheckNeeded = 7;
// Bit positions for bit field 2
static const int kIsExtensible = 0;
static const int kStringWrapperSafeForDefaultValueOf = 1;
static const int kAttachedToSharedFunctionInfo = 2;
// No bits can be used after kElementsKindFirstBit, they are all reserved for
// storing ElementKind.
static const int kElementsKindShift = 3;
static const int kElementsKindBitCount = 5;
// Derived values from bit field 2
static const int kElementsKindMask = (-1 << kElementsKindShift) &
((1 << (kElementsKindShift + kElementsKindBitCount)) - 1);
static const int8_t kMaximumBitField2FastElementValue = static_cast<int8_t>(
(FAST_ELEMENTS + 1) << Map::kElementsKindShift) - 1;
static const int8_t kMaximumBitField2FastSmiElementValue =
static_cast<int8_t>((FAST_SMI_ELEMENTS + 1) <<
Map::kElementsKindShift) - 1;
static const int8_t kMaximumBitField2FastHoleyElementValue =
static_cast<int8_t>((FAST_HOLEY_ELEMENTS + 1) <<
Map::kElementsKindShift) - 1;
static const int8_t kMaximumBitField2FastHoleySmiElementValue =
static_cast<int8_t>((FAST_HOLEY_SMI_ELEMENTS + 1) <<
Map::kElementsKindShift) - 1;
typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
kPointerFieldsEndOffset,
kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
};
// An abstract superclass, a marker class really, for simple structure classes.
// It doesn't carry much functionality but allows struct classes to be
// identified in the type system.
class Struct: public HeapObject {
public:
inline void InitializeBody(int object_size);
static inline Struct* cast(Object* that);
};
// Script describes a script which has been added to the VM.
class Script: public Struct {
public:
// Script types.
enum Type {
TYPE_NATIVE = 0,
TYPE_EXTENSION = 1,
TYPE_NORMAL = 2
};
// Script compilation types.
enum CompilationType {
COMPILATION_TYPE_HOST = 0,
COMPILATION_TYPE_EVAL = 1
};
// Script compilation state.
enum CompilationState {
COMPILATION_STATE_INITIAL = 0,
COMPILATION_STATE_COMPILED = 1
};
// [source]: the script source.
DECL_ACCESSORS(source, Object)
// [name]: the script name.
DECL_ACCESSORS(name, Object)
// [id]: the script id.
DECL_ACCESSORS(id, Object)
// [line_offset]: script line offset in resource from where it was extracted.
DECL_ACCESSORS(line_offset, Smi)
// [column_offset]: script column offset in resource from where it was
// extracted.
DECL_ACCESSORS(column_offset, Smi)
// [data]: additional data associated with this script.
DECL_ACCESSORS(data, Object)
// [context_data]: context data for the context this script was compiled in.
DECL_ACCESSORS(context_data, Object)
// [wrapper]: the wrapper cache.
DECL_ACCESSORS(wrapper, Foreign)
// [type]: the script type.
DECL_ACCESSORS(type, Smi)
// [compilation]: how the the script was compiled.
DECL_ACCESSORS(compilation_type, Smi)
// [is_compiled]: determines whether the script has already been compiled.
DECL_ACCESSORS(compilation_state, Smi)
// [line_ends]: FixedArray of line ends positions.
DECL_ACCESSORS(line_ends, Object)
// [eval_from_shared]: for eval scripts the shared funcion info for the
// function from which eval was called.
DECL_ACCESSORS(eval_from_shared, Object)
// [eval_from_instructions_offset]: the instruction offset in the code for the
// function from which eval was called where eval was called.
DECL_ACCESSORS(eval_from_instructions_offset, Smi)
static inline Script* cast(Object* obj);
// If script source is an external string, check that the underlying
// resource is accessible. Otherwise, always return true.
inline bool HasValidSource();
#ifdef OBJECT_PRINT
inline void ScriptPrint() {
ScriptPrint(stdout);
}
void ScriptPrint(FILE* out);
#endif
DECLARE_VERIFIER(Script)
static const int kSourceOffset = HeapObject::kHeaderSize;
static const int kNameOffset = kSourceOffset + kPointerSize;
static const int kLineOffsetOffset = kNameOffset + kPointerSize;
static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
static const int kContextOffset = kDataOffset + kPointerSize;
static const int kWrapperOffset = kContextOffset + kPointerSize;
static const int kTypeOffset = kWrapperOffset + kPointerSize;
static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
static const int kCompilationStateOffset =
kCompilationTypeOffset + kPointerSize;
static const int kLineEndsOffset = kCompilationStateOffset + kPointerSize;
static const int kIdOffset = kLineEndsOffset + kPointerSize;
static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
static const int kEvalFrominstructionsOffsetOffset =
kEvalFromSharedOffset + kPointerSize;
static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
};
// List of builtin functions we want to identify to improve code
// generation.
//
// Each entry has a name of a global object property holding an object
// optionally followed by ".prototype", a name of a builtin function
// on the object (the one the id is set for), and a label.
//
// Installation of ids for the selected builtin functions is handled
// by the bootstrapper.
//
// NOTE: Order is important: math functions should be at the end of
// the list and MathFloor should be the first math function.
#define FUNCTIONS_WITH_ID_LIST(V) \
V(Array.prototype, push, ArrayPush) \
V(Array.prototype, pop, ArrayPop) \
V(Function.prototype, apply, FunctionApply) \
V(String.prototype, charCodeAt, StringCharCodeAt) \
V(String.prototype, charAt, StringCharAt) \
V(String, fromCharCode, StringFromCharCode) \
V(Math, floor, MathFloor) \
V(Math, round, MathRound) \
V(Math, ceil, MathCeil) \
V(Math, abs, MathAbs) \
V(Math, log, MathLog) \
V(Math, sin, MathSin) \
V(Math, cos, MathCos) \
V(Math, tan, MathTan) \
V(Math, asin, MathASin) \
V(Math, acos, MathACos) \
V(Math, atan, MathATan) \
V(Math, exp, MathExp) \
V(Math, sqrt, MathSqrt) \
V(Math, pow, MathPow) \
V(Math, random, MathRandom) \
V(Math, max, MathMax) \
V(Math, min, MathMin)
enum BuiltinFunctionId {
#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
k##name,
FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
#undef DECLARE_FUNCTION_ID
// Fake id for a special case of Math.pow. Note, it continues the
// list of math functions.
kMathPowHalf,
kFirstMathFunctionId = kMathFloor
};
// SharedFunctionInfo describes the JSFunction information that can be
// shared by multiple instances of the function.
class SharedFunctionInfo: public HeapObject {
public:
// [name]: Function name.
DECL_ACCESSORS(name, Object)
// [code]: Function code.
DECL_ACCESSORS(code, Code)
// [optimized_code_map]: Map from native context to optimized code
// and a shared literals array or Smi 0 if none.
DECL_ACCESSORS(optimized_code_map, Object)
// Returns index i of the entry with the specified context. At position
// i - 1 is the context, position i the code, and i + 1 the literals array.
// Returns -1 when no matching entry is found.
int SearchOptimizedCodeMap(Context* native_context);
// Installs optimized code from the code map on the given closure. The
// index has to be consistent with a search result as defined above.
void InstallFromOptimizedCodeMap(JSFunction* function, int index);
// Clear optimized code map.
void ClearOptimizedCodeMap();
// Add a new entry to the optimized code map.
static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared,
Handle<Context> native_context,
Handle<Code> code,
Handle<FixedArray> literals);
static const int kEntryLength = 3;
// [scope_info]: Scope info.
DECL_ACCESSORS(scope_info, ScopeInfo)
// [construct stub]: Code stub for constructing instances of this function.
DECL_ACCESSORS(construct_stub, Code)
inline Code* unchecked_code();
// Returns if this function has been compiled to native code yet.
inline bool is_compiled();
// [length]: The function length - usually the number of declared parameters.
// Use up to 2^30 parameters.
inline int length();
inline void set_length(int value);
// [formal parameter count]: The declared number of parameters.
inline int formal_parameter_count();
inline void set_formal_parameter_count(int value);
// Set the formal parameter count so the function code will be
// called without using argument adaptor frames.
inline void DontAdaptArguments();
// [expected_nof_properties]: Expected number of properties for the function.
inline int expected_nof_properties();
inline void set_expected_nof_properties(int value);
// Inobject slack tracking is the way to reclaim unused inobject space.
//
// The instance size is initially determined by adding some slack to
// expected_nof_properties (to allow for a few extra properties added
// after the constructor). There is no guarantee that the extra space
// will not be wasted.
//
// Here is the algorithm to reclaim the unused inobject space:
// - Detect the first constructor call for this SharedFunctionInfo.
// When it happens enter the "in progress" state: remember the
// constructor's initial_map and install a special construct stub that
// counts constructor calls.
// - While the tracking is in progress create objects filled with
// one_pointer_filler_map instead of undefined_value. This way they can be
// resized quickly and safely.
// - Once enough (kGenerousAllocationCount) objects have been created
// compute the 'slack' (traverse the map transition tree starting from the
// initial_map and find the lowest value of unused_property_fields).
// - Traverse the transition tree again and decrease the instance size
// of every map. Existing objects will resize automatically (they are
// filled with one_pointer_filler_map). All further allocations will
// use the adjusted instance size.
// - Decrease expected_nof_properties so that an allocations made from
// another context will use the adjusted instance size too.
// - Exit "in progress" state by clearing the reference to the initial_map
// and setting the regular construct stub (generic or inline).
//
// The above is the main event sequence. Some special cases are possible
// while the tracking is in progress:
//
// - GC occurs.
// Check if the initial_map is referenced by any live objects (except this
// SharedFunctionInfo). If it is, continue tracking as usual.
// If it is not, clear the reference and reset the tracking state. The
// tracking will be initiated again on the next constructor call.
//
// - The constructor is called from another context.
// Immediately complete the tracking, perform all the necessary changes
// to maps. This is necessary because there is no efficient way to track
// multiple initial_maps.
// Proceed to create an object in the current context (with the adjusted
// size).
//
// - A different constructor function sharing the same SharedFunctionInfo is
// called in the same context. This could be another closure in the same
// context, or the first function could have been disposed.
// This is handled the same way as the previous case.
//
// Important: inobject slack tracking is not attempted during the snapshot
// creation.
static const int kGenerousAllocationCount = 8;
// [construction_count]: Counter for constructor calls made during
// the tracking phase.
inline int construction_count();
inline void set_construction_count(int value);
// [initial_map]: initial map of the first function called as a constructor.
// Saved for the duration of the tracking phase.
// This is a weak link (GC resets it to undefined_value if no other live
// object reference this map).
DECL_ACCESSORS(initial_map, Object)
// True if the initial_map is not undefined and the countdown stub is
// installed.
inline bool IsInobjectSlackTrackingInProgress();
// Starts the tracking.
// Stores the initial map and installs the countdown stub.
// IsInobjectSlackTrackingInProgress is normally true after this call,
// except when tracking have not been started (e.g. the map has no unused
// properties or the snapshot is being built).
void StartInobjectSlackTracking(Map* map);
// Completes the tracking.
// IsInobjectSlackTrackingInProgress is false after this call.
void CompleteInobjectSlackTracking();
// Invoked before pointers in SharedFunctionInfo are being marked.
// Also clears the optimized code map.
inline void BeforeVisitingPointers();
// Clears the initial_map before the GC marking phase to ensure the reference
// is weak. IsInobjectSlackTrackingInProgress is false after this call.
void DetachInitialMap();
// Restores the link to the initial map after the GC marking phase.
// IsInobjectSlackTrackingInProgress is true after this call.
void AttachInitialMap(Map* map);
// False if there are definitely no live objects created from this function.
// True if live objects _may_ exist (existence not guaranteed).
// May go back from true to false after GC.
DECL_BOOLEAN_ACCESSORS(live_objects_may_exist)
// [instance class name]: class name for instances.
DECL_ACCESSORS(instance_class_name, Object)
// [function data]: This field holds some additional data for function.
// Currently it either has FunctionTemplateInfo to make benefit the API
// or Smi identifying a builtin function.
// In the long run we don't want all functions to have this field but
// we can fix that when we have a better model for storing hidden data
// on objects.
DECL_ACCESSORS(function_data, Object)
inline bool IsApiFunction();
inline FunctionTemplateInfo* get_api_func_data();
inline bool HasBuiltinFunctionId();
inline BuiltinFunctionId builtin_function_id();
// [script info]: Script from which the function originates.
DECL_ACCESSORS(script, Object)
// [num_literals]: Number of literals used by this function.
inline int num_literals();
inline void set_num_literals(int value);
// [start_position_and_type]: Field used to store both the source code
// position, whether or not the function is a function expression,
// and whether or not the function is a toplevel function. The two
// least significants bit indicates whether the function is an
// expression and the rest contains the source code position.
inline int start_position_and_type();
inline void set_start_position_and_type(int value);
// [debug info]: Debug information.
DECL_ACCESSORS(debug_info, Object)
// [inferred name]: Name inferred from variable or property
// assignment of this function. Used to facilitate debugging and
// profiling of JavaScript code written in OO style, where almost
// all functions are anonymous but are assigned to object
// properties.
DECL_ACCESSORS(inferred_name, String)
// The function's name if it is non-empty, otherwise the inferred name.
String* DebugName();
// Position of the 'function' token in the script source.
inline int function_token_position();
inline void set_function_token_position(int function_token_position);
// Position of this function in the script source.
inline int start_position();
inline void set_start_position(int start_position);
// End position of this function in the script source.
inline int end_position();
inline void set_end_position(int end_position);
// Is this function a function expression in the source code.
DECL_BOOLEAN_ACCESSORS(is_expression)
// Is this function a top-level function (scripts, evals).
DECL_BOOLEAN_ACCESSORS(is_toplevel)
// Bit field containing various information collected by the compiler to
// drive optimization.
inline int compiler_hints();
inline void set_compiler_hints(int value);
inline int ast_node_count();
inline void set_ast_node_count(int count);
// A counter used to determine when to stress the deoptimizer with a
// deopt.
inline int stress_deopt_counter();
inline void set_stress_deopt_counter(int counter);
inline int profiler_ticks();
// Inline cache age is used to infer whether the function survived a context
// disposal or not. In the former case we reset the opt_count.
inline int ic_age();
inline void set_ic_age(int age);
// Add information on assignments of the form this.x = ...;
void SetThisPropertyAssignmentsInfo(
bool has_only_simple_this_property_assignments,
FixedArray* this_property_assignments);
// Clear information on assignments of the form this.x = ...;
void ClearThisPropertyAssignmentsInfo();
// Indicate that this function only consists of assignments of the form
// this.x = y; where y is either a constant or refers to an argument.
inline bool has_only_simple_this_property_assignments();
// Indicates if this function can be lazy compiled.
// This is used to determine if we can safely flush code from a function
// when doing GC if we expect that the function will no longer be used.
DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation)
// Indicates if this function can be lazy compiled without a context.
// This is used to determine if we can force compilation without reaching
// the function through program execution but through other means (e.g. heap
// iteration by the debugger).
DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation_without_context)
// Indicates how many full GCs this function has survived with assigned
// code object. Used to determine when it is relatively safe to flush
// this code object and replace it with lazy compilation stub.
// Age is reset when GC notices that the code object is referenced
// from the stack or compilation cache.
inline int code_age();
inline void set_code_age(int age);
// Indicates whether optimizations have been disabled for this
// shared function info. If a function is repeatedly optimized or if
// we cannot optimize the function we disable optimization to avoid
// spending time attempting to optimize it again.
DECL_BOOLEAN_ACCESSORS(optimization_disabled)
// Indicates the language mode of the function's code as defined by the
// current harmony drafts for the next ES language standard. Possible
// values are:
// 1. CLASSIC_MODE - Unrestricted syntax and semantics, same as in ES5.
// 2. STRICT_MODE - Restricted syntax and semantics, same as in ES5.
// 3. EXTENDED_MODE - Only available under the harmony flag, not part of ES5.
inline LanguageMode language_mode();
inline void set_language_mode(LanguageMode language_mode);
// Indicates whether the language mode of this function is CLASSIC_MODE.
inline bool is_classic_mode();
// Indicates whether the language mode of this function is EXTENDED_MODE.
inline bool is_extended_mode();
// False if the function definitely does not allocate an arguments object.
DECL_BOOLEAN_ACCESSORS(uses_arguments)
// True if the function has any duplicated parameter names.
DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters)
// Indicates whether the function is a native function.
// These needs special treatment in .call and .apply since
// null passed as the receiver should not be translated to the
// global object.
DECL_BOOLEAN_ACCESSORS(native)
// Indicates that the function was created by the Function function.
// Though it's anonymous, toString should treat it as if it had the name
// "anonymous". We don't set the name itself so that the system does not
// see a binding for it.
DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous)
// Indicates whether the function is a bound function created using
// the bind function.
DECL_BOOLEAN_ACCESSORS(bound)
// Indicates that the function is anonymous (the name field can be set
// through the API, which does not change this flag).
DECL_BOOLEAN_ACCESSORS(is_anonymous)
// Is this a function or top-level/eval code.
DECL_BOOLEAN_ACCESSORS(is_function)
// Indicates that the function cannot be optimized.
DECL_BOOLEAN_ACCESSORS(dont_optimize)
// Indicates that the function cannot be inlined.
DECL_BOOLEAN_ACCESSORS(dont_inline)
// Indicates that code for this function cannot be cached.
DECL_BOOLEAN_ACCESSORS(dont_cache)
// Indicates whether or not the code in the shared function support
// deoptimization.
inline bool has_deoptimization_support();
// Enable deoptimization support through recompiled code.
void EnableDeoptimizationSupport(Code* recompiled);
// Disable (further) attempted optimization of all functions sharing this
// shared function info.
void DisableOptimization(const char* reason);
// Lookup the bailout ID and ASSERT that it exists in the non-optimized
// code, returns whether it asserted (i.e., always true if assertions are
// disabled).
bool VerifyBailoutId(BailoutId id);
// Check whether a inlined constructor can be generated with the given
// prototype.
bool CanGenerateInlineConstructor(Object* prototype);
// Prevents further attempts to generate inline constructors.
// To be called if generation failed for any reason.
void ForbidInlineConstructor();
// For functions which only contains this property assignments this provides
// access to the names for the properties assigned.
DECL_ACCESSORS(this_property_assignments, Object)
inline int this_property_assignments_count();
inline void set_this_property_assignments_count(int value);
String* GetThisPropertyAssignmentName(int index);
bool IsThisPropertyAssignmentArgument(int index);
int GetThisPropertyAssignmentArgument(int index);
Object* GetThisPropertyAssignmentConstant(int index);
// [source code]: Source code for the function.
bool HasSourceCode();
Handle<Object> GetSourceCode();
// Number of times the function was optimized.
inline int opt_count();
inline void set_opt_count(int opt_count);
// Number of times the function was deoptimized.
inline void set_deopt_count(int value);
inline int deopt_count();
inline void increment_deopt_count();
// Number of time we tried to re-enable optimization after it
// was disabled due to high number of deoptimizations.
inline void set_opt_reenable_tries(int value);
inline int opt_reenable_tries();
inline void TryReenableOptimization();
// Stores deopt_count, opt_reenable_tries and ic_age as bit-fields.
inline void set_counters(int value);
inline int counters();
// Source size of this function.
int SourceSize();
// Calculate the instance size.
int CalculateInstanceSize();
// Calculate the number of in-object properties.
int CalculateInObjectProperties();
// Dispatched behavior.
// Set max_length to -1 for unlimited length.
void SourceCodePrint(StringStream* accumulator, int max_length);
#ifdef OBJECT_PRINT
inline void SharedFunctionInfoPrint() {
SharedFunctionInfoPrint(stdout);
}
void SharedFunctionInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(SharedFunctionInfo)
void ResetForNewContext(int new_ic_age);
// Helper to compile the shared code. Returns true on success, false on
// failure (e.g., stack overflow during compilation). This is only used by
// the debugger, it is not possible to compile without a context otherwise.
static bool CompileLazy(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag);
// Casting.
static inline SharedFunctionInfo* cast(Object* obj);
// Constants.
static const int kDontAdaptArgumentsSentinel = -1;
// Layout description.
// Pointer fields.
static const int kNameOffset = HeapObject::kHeaderSize;
static const int kCodeOffset = kNameOffset + kPointerSize;
static const int kOptimizedCodeMapOffset = kCodeOffset + kPointerSize;
static const int kScopeInfoOffset = kOptimizedCodeMapOffset + kPointerSize;
static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
static const int kInstanceClassNameOffset =
kConstructStubOffset + kPointerSize;
static const int kFunctionDataOffset =
kInstanceClassNameOffset + kPointerSize;
static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
static const int kInitialMapOffset =
kInferredNameOffset + kPointerSize;
static const int kThisPropertyAssignmentsOffset =
kInitialMapOffset + kPointerSize;
// ast_node_count is a Smi field. It could be grouped with another Smi field
// into a PSEUDO_SMI_ACCESSORS pair (on x64), if one becomes available.
static const int kAstNodeCountOffset =
kThisPropertyAssignmentsOffset + kPointerSize;
#if V8_HOST_ARCH_32_BIT
// Smi fields.
static const int kLengthOffset =
kAstNodeCountOffset + kPointerSize;
static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
static const int kExpectedNofPropertiesOffset =
kFormalParameterCountOffset + kPointerSize;
static const int kNumLiteralsOffset =
kExpectedNofPropertiesOffset + kPointerSize;
static const int kStartPositionAndTypeOffset =
kNumLiteralsOffset + kPointerSize;
static const int kEndPositionOffset =
kStartPositionAndTypeOffset + kPointerSize;
static const int kFunctionTokenPositionOffset =
kEndPositionOffset + kPointerSize;
static const int kCompilerHintsOffset =
kFunctionTokenPositionOffset + kPointerSize;
static const int kThisPropertyAssignmentsCountOffset =
kCompilerHintsOffset + kPointerSize;
static const int kOptCountOffset =
kThisPropertyAssignmentsCountOffset + kPointerSize;
static const int kCountersOffset = kOptCountOffset + kPointerSize;
static const int kStressDeoptCounterOffset = kCountersOffset + kPointerSize;
// Total size.
static const int kSize = kStressDeoptCounterOffset + kPointerSize;
#else
// The only reason to use smi fields instead of int fields
// is to allow iteration without maps decoding during
// garbage collections.
// To avoid wasting space on 64-bit architectures we use
// the following trick: we group integer fields into pairs
// The least significant integer in each pair is shifted left by 1.
// By doing this we guarantee that LSB of each kPointerSize aligned
// word is not set and thus this word cannot be treated as pointer
// to HeapObject during old space traversal.
#if __BYTE_ORDER == __LITTLE_ENDIAN
static const int kLengthOffset =
kAstNodeCountOffset + kPointerSize;
static const int kFormalParameterCountOffset =
kLengthOffset + kIntSize;
static const int kExpectedNofPropertiesOffset =
kFormalParameterCountOffset + kIntSize;
static const int kNumLiteralsOffset =
kExpectedNofPropertiesOffset + kIntSize;
static const int kEndPositionOffset =
kNumLiteralsOffset + kIntSize;
static const int kStartPositionAndTypeOffset =
kEndPositionOffset + kIntSize;
static const int kFunctionTokenPositionOffset =
kStartPositionAndTypeOffset + kIntSize;
static const int kCompilerHintsOffset =
kFunctionTokenPositionOffset + kIntSize;
static const int kThisPropertyAssignmentsCountOffset =
kCompilerHintsOffset + kIntSize;
static const int kOptCountOffset =
kThisPropertyAssignmentsCountOffset + kIntSize;
static const int kCountersOffset = kOptCountOffset + kIntSize;
static const int kStressDeoptCounterOffset = kCountersOffset + kIntSize;
#elif __BYTE_ORDER == __BIG_ENDIAN
static const int kFormalParameterCountOffset =
kAstNodeCountOffset + kPointerSize;
static const int kLengthOffset =
kFormalParameterCountOffset + kIntSize;
static const int kNumLiteralsOffset =
kLengthOffset + kIntSize;
static const int kExpectedNofPropertiesOffset =
kNumLiteralsOffset + kIntSize;
static const int kStartPositionAndTypeOffset =
kExpectedNofPropertiesOffset + kIntSize;
static const int kEndPositionOffset =
kStartPositionAndTypeOffset + kIntSize;
static const int kCompilerHintsOffset =
kEndPositionOffset + kIntSize;
static const int kFunctionTokenPositionOffset =
kCompilerHintsOffset + kIntSize;
static const int kOptCountOffset =
kFunctionTokenPositionOffset + kIntSize;
static const int kThisPropertyAssignmentsCountOffset =
kOptCountOffset + kIntSize;
static const int kStressDeoptCounterOffset =
kThisPropertyAssignmentsCountOffset + kIntSize;
static const int kCountersOffset = kStressDeoptCounterOffset + kIntSize;
#else
#error Unknown byte ordering
#endif
// Total size.
static const int kSize = kStressDeoptCounterOffset + kIntSize;
#endif
// The construction counter for inobject slack tracking is stored in the
// most significant byte of compiler_hints which is otherwise unused.
// Its offset depends on the endian-ness of the architecture.
#if __BYTE_ORDER == __LITTLE_ENDIAN
static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
#elif __BYTE_ORDER == __BIG_ENDIAN
static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
#else
#error Unknown byte ordering
#endif
static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
typedef FixedBodyDescriptor<kNameOffset,
kThisPropertyAssignmentsOffset + kPointerSize,
kSize> BodyDescriptor;
// Bit positions in start_position_and_type.
// The source code start position is in the 30 most significant bits of
// the start_position_and_type field.
static const int kIsExpressionBit = 0;
static const int kIsTopLevelBit = 1;
static const int kStartPositionShift = 2;
static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
// Bit positions in compiler_hints.
static const int kCodeAgeSize = 3;
static const int kCodeAgeMask = (1 << kCodeAgeSize) - 1;
enum CompilerHints {
kHasOnlySimpleThisPropertyAssignments,
kAllowLazyCompilation,
kAllowLazyCompilationWithoutContext,
kLiveObjectsMayExist,
kCodeAgeShift,
kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
kStrictModeFunction,
kExtendedModeFunction,
kUsesArguments,
kHasDuplicateParameters,
kNative,
kBoundFunction,
kIsAnonymous,
kNameShouldPrintAsAnonymous,
kIsFunction,
kDontOptimize,
kDontInline,
kDontCache,
kCompilerHintsCount // Pseudo entry
};
class DeoptCountBits: public BitField<int, 0, 4> {};
class OptReenableTriesBits: public BitField<int, 4, 18> {};
class ICAgeBits: public BitField<int, 22, 8> {};
private:
#if V8_HOST_ARCH_32_BIT
// On 32 bit platforms, compiler hints is a smi.
static const int kCompilerHintsSmiTagSize = kSmiTagSize;
static const int kCompilerHintsSize = kPointerSize;
#else
// On 64 bit platforms, compiler hints is not a smi, see comment above.
static const int kCompilerHintsSmiTagSize = 0;
static const int kCompilerHintsSize = kIntSize;
#endif
STATIC_ASSERT(SharedFunctionInfo::kCompilerHintsCount <=
SharedFunctionInfo::kCompilerHintsSize * kBitsPerByte);
public:
// Constants for optimizing codegen for strict mode function and
// native tests.
// Allows to use byte-width instructions.
static const int kStrictModeBitWithinByte =
(kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
static const int kExtendedModeBitWithinByte =
(kExtendedModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
static const int kNativeBitWithinByte =
(kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;
#if __BYTE_ORDER == __LITTLE_ENDIAN
static const int kStrictModeByteOffset = kCompilerHintsOffset +
(kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
static const int kExtendedModeByteOffset = kCompilerHintsOffset +
(kExtendedModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
static const int kNativeByteOffset = kCompilerHintsOffset +
(kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
#elif __BYTE_ORDER == __BIG_ENDIAN
static const int kStrictModeByteOffset = kCompilerHintsOffset +
(kCompilerHintsSize - 1) -
((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
static const int kExtendedModeByteOffset = kCompilerHintsOffset +
(kCompilerHintsSize - 1) -
((kExtendedModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
static const int kNativeByteOffset = kCompilerHintsOffset +
(kCompilerHintsSize - 1) -
((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte);
#else
#error Unknown byte ordering
#endif
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
};
// Representation for module instance objects.
class JSModule: public JSObject {
public:
// [context]: the context holding the module's locals, or undefined if none.
DECL_ACCESSORS(context, Object)
// [scope_info]: Scope info.
DECL_ACCESSORS(scope_info, ScopeInfo)
// Casting.
static inline JSModule* cast(Object* obj);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSModulePrint() {
JSModulePrint(stdout);
}
void JSModulePrint(FILE* out);
#endif
DECLARE_VERIFIER(JSModule)
// Layout description.
static const int kContextOffset = JSObject::kHeaderSize;
static const int kScopeInfoOffset = kContextOffset + kPointerSize;
static const int kSize = kScopeInfoOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSModule);
};
// JSFunction describes JavaScript functions.
class JSFunction: public JSObject {
public:
// [prototype_or_initial_map]:
DECL_ACCESSORS(prototype_or_initial_map, Object)
// [shared]: The information about the function that
// can be shared by instances.
DECL_ACCESSORS(shared, SharedFunctionInfo)
inline SharedFunctionInfo* unchecked_shared();
// [context]: The context for this function.
inline Context* context();
inline Object* unchecked_context();
inline void set_context(Object* context);
// [code]: The generated code object for this function. Executed
// when the function is invoked, e.g. foo() or new foo(). See
// [[Call]] and [[Construct]] description in ECMA-262, section
// 8.6.2, page 27.
inline Code* code();
inline void set_code(Code* code);
inline void ReplaceCode(Code* code);
inline Code* unchecked_code();
// Tells whether this function is builtin.
inline bool IsBuiltin();
// Tells whether or not the function needs arguments adaption.
inline bool NeedsArgumentsAdaption();
// Tells whether or not this function has been optimized.
inline bool IsOptimized();
// Tells whether or not this function can be optimized.
inline bool IsOptimizable();
// Mark this function for lazy recompilation. The function will be
// recompiled the next time it is executed.
void MarkForLazyRecompilation();
void MarkForParallelRecompilation();
// Helpers to compile this function. Returns true on success, false on
// failure (e.g., stack overflow during compilation).
static bool EnsureCompiled(Handle<JSFunction> function,
ClearExceptionFlag flag);
static bool CompileLazy(Handle<JSFunction> function,
ClearExceptionFlag flag);
static bool CompileOptimized(Handle<JSFunction> function,
BailoutId osr_ast_id,
ClearExceptionFlag flag);
// Tells whether or not the function is already marked for lazy
// recompilation.
inline bool IsMarkedForLazyRecompilation();
inline bool IsMarkedForParallelRecompilation();
// Tells whether or not the function is on the parallel
// recompilation queue.
inline bool IsInRecompileQueue();
// Check whether or not this function is inlineable.
bool IsInlineable();
// [literals_or_bindings]: Fixed array holding either
// the materialized literals or the bindings of a bound function.
//
// If the function contains object, regexp or array literals, the
// literals array prefix contains the object, regexp, and array
// function to be used when creating these literals. This is
// necessary so that we do not dynamically lookup the object, regexp
// or array functions. Performing a dynamic lookup, we might end up
// using the functions from a new context that we should not have
// access to.
//
// On bound functions, the array is a (copy-on-write) fixed-array containing
// the function that was bound, bound this-value and any bound
// arguments. Bound functions never contain literals.
DECL_ACCESSORS(literals_or_bindings, FixedArray)
inline FixedArray* literals();
inline void set_literals(FixedArray* literals);
inline FixedArray* function_bindings();
inline void set_function_bindings(FixedArray* bindings);
// The initial map for an object created by this constructor.
inline Map* initial_map();
inline void set_initial_map(Map* value);
inline bool has_initial_map();
// Get and set the prototype property on a JSFunction. If the
// function has an initial map the prototype is set on the initial
// map. Otherwise, the prototype is put in the initial map field
// until an initial map is needed.
inline bool has_prototype();
inline bool has_instance_prototype();
inline Object* prototype();
inline Object* instance_prototype();
MUST_USE_RESULT MaybeObject* SetInstancePrototype(Object* value);
MUST_USE_RESULT MaybeObject* SetPrototype(Object* value);
// After prototype is removed, it will not be created when accessed, and
// [[Construct]] from this function will not be allowed.
void RemovePrototype();
inline bool should_have_prototype();
// Accessor for this function's initial map's [[class]]
// property. This is primarily used by ECMA native functions. This
// method sets the class_name field of this function's initial map
// to a given value. It creates an initial map if this function does
// not have one. Note that this method does not copy the initial map
// if it has one already, but simply replaces it with the new value.
// Instances created afterwards will have a map whose [[class]] is
// set to 'value', but there is no guarantees on instances created
// before.
void SetInstanceClassName(String* name);
// Returns if this function has been compiled to native code yet.
inline bool is_compiled();
// [next_function_link]: Field for linking functions. This list is treated as
// a weak list by the GC.
DECL_ACCESSORS(next_function_link, Object)
// Prints the name of the function using PrintF.
inline void PrintName() {
PrintName(stdout);
}
void PrintName(FILE* out);
// Casting.
static inline JSFunction* cast(Object* obj);
// Iterates the objects, including code objects indirectly referenced
// through pointers to the first instruction in the code object.
void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSFunctionPrint() {
JSFunctionPrint(stdout);
}
void JSFunctionPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSFunction)
// Returns the number of allocated literals.
inline int NumberOfLiterals();
// Retrieve the native context from a function's literal array.
static Context* NativeContextFromLiterals(FixedArray* literals);
// Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
// kSize) is weak and has special handling during garbage collection.
static const int kCodeEntryOffset = JSObject::kHeaderSize;
static const int kPrototypeOrInitialMapOffset =
kCodeEntryOffset + kPointerSize;
static const int kSharedFunctionInfoOffset =
kPrototypeOrInitialMapOffset + kPointerSize;
static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
static const int kLiteralsOffset = kContextOffset + kPointerSize;
static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize;
static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
static const int kSize = kNextFunctionLinkOffset + kPointerSize;
// Layout of the literals array.
static const int kLiteralsPrefixSize = 1;
static const int kLiteralNativeContextIndex = 0;
// Layout of the bound-function binding array.
static const int kBoundFunctionIndex = 0;
static const int kBoundThisIndex = 1;
static const int kBoundArgumentsStartIndex = 2;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
};
// JSGlobalProxy's prototype must be a JSGlobalObject or null,
// and the prototype is hidden. JSGlobalProxy always delegates
// property accesses to its prototype if the prototype is not null.
//
// A JSGlobalProxy can be reinitialized which will preserve its identity.
//
// Accessing a JSGlobalProxy requires security check.
class JSGlobalProxy : public JSObject {
public:
// [native_context]: the owner native context of this global proxy object.
// It is null value if this object is not used by any context.
DECL_ACCESSORS(native_context, Object)
// Casting.
static inline JSGlobalProxy* cast(Object* obj);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSGlobalProxyPrint() {
JSGlobalProxyPrint(stdout);
}
void JSGlobalProxyPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSGlobalProxy)
// Layout description.
static const int kNativeContextOffset = JSObject::kHeaderSize;
static const int kSize = kNativeContextOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
};
// Forward declaration.
class JSBuiltinsObject;
// Common super class for JavaScript global objects and the special
// builtins global objects.
class GlobalObject: public JSObject {
public:
// [builtins]: the object holding the runtime routines written in JS.
DECL_ACCESSORS(builtins, JSBuiltinsObject)
// [native context]: the natives corresponding to this global object.
DECL_ACCESSORS(native_context, Context)
// [global context]: the most recent (i.e. innermost) global context.
DECL_ACCESSORS(global_context, Context)
// [global receiver]: the global receiver object of the context
DECL_ACCESSORS(global_receiver, JSObject)
// Retrieve the property cell used to store a property.
JSGlobalPropertyCell* GetPropertyCell(LookupResult* result);
// This is like GetProperty, but is used when you know the lookup won't fail
// by throwing an exception. This is for the debug and builtins global
// objects, where it is known which properties can be expected to be present
// on the object.
Object* GetPropertyNoExceptionThrown(String* key) {
Object* answer = GetProperty(key)->ToObjectUnchecked();
return answer;
}
// Ensure that the global object has a cell for the given property name.
static Handle<JSGlobalPropertyCell> EnsurePropertyCell(
Handle<GlobalObject> global,
Handle<String> name);
// TODO(kmillikin): This function can be eliminated once the stub cache is
// full handlified (and the static helper can be written directly).
MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
// Casting.
static inline GlobalObject* cast(Object* obj);
// Layout description.
static const int kBuiltinsOffset = JSObject::kHeaderSize;
static const int kNativeContextOffset = kBuiltinsOffset + kPointerSize;
static const int kGlobalContextOffset = kNativeContextOffset + kPointerSize;
static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
};
// JavaScript global object.
class JSGlobalObject: public GlobalObject {
public:
// Casting.
static inline JSGlobalObject* cast(Object* obj);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSGlobalObjectPrint() {
JSGlobalObjectPrint(stdout);
}
void JSGlobalObjectPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSGlobalObject)
// Layout description.
static const int kSize = GlobalObject::kHeaderSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
};
// Builtins global object which holds the runtime routines written in
// JavaScript.
class JSBuiltinsObject: public GlobalObject {
public:
// Accessors for the runtime routines written in JavaScript.
inline Object* javascript_builtin(Builtins::JavaScript id);
inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
// Accessors for code of the runtime routines written in JavaScript.
inline Code* javascript_builtin_code(Builtins::JavaScript id);
inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value);
// Casting.
static inline JSBuiltinsObject* cast(Object* obj);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSBuiltinsObjectPrint() {
JSBuiltinsObjectPrint(stdout);
}
void JSBuiltinsObjectPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSBuiltinsObject)
// Layout description. The size of the builtins object includes
// room for two pointers per runtime routine written in javascript
// (function and code object).
static const int kJSBuiltinsCount = Builtins::id_count;
static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
static const int kJSBuiltinsCodeOffset =
GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize);
static const int kSize =
kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize);
static int OffsetOfFunctionWithId(Builtins::JavaScript id) {
return kJSBuiltinsOffset + id * kPointerSize;
}
static int OffsetOfCodeWithId(Builtins::JavaScript id) {
return kJSBuiltinsCodeOffset + id * kPointerSize;
}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
};
// Representation for JS Wrapper objects, String, Number, Boolean, etc.
class JSValue: public JSObject {
public:
// [value]: the object being wrapped.
DECL_ACCESSORS(value, Object)
// Casting.
static inline JSValue* cast(Object* obj);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSValuePrint() {
JSValuePrint(stdout);
}
void JSValuePrint(FILE* out);
#endif
DECLARE_VERIFIER(JSValue)
// Layout description.
static const int kValueOffset = JSObject::kHeaderSize;
static const int kSize = kValueOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
};
class DateCache;
// Representation for JS date objects.
class JSDate: public JSObject {
public:
// If one component is NaN, all of them are, indicating a NaN time value.
// [value]: the time value.
DECL_ACCESSORS(value, Object)
// [year]: caches year. Either undefined, smi, or NaN.
DECL_ACCESSORS(year, Object)
// [month]: caches month. Either undefined, smi, or NaN.
DECL_ACCESSORS(month, Object)
// [day]: caches day. Either undefined, smi, or NaN.
DECL_ACCESSORS(day, Object)
// [weekday]: caches day of week. Either undefined, smi, or NaN.
DECL_ACCESSORS(weekday, Object)
// [hour]: caches hours. Either undefined, smi, or NaN.
DECL_ACCESSORS(hour, Object)
// [min]: caches minutes. Either undefined, smi, or NaN.
DECL_ACCESSORS(min, Object)
// [sec]: caches seconds. Either undefined, smi, or NaN.
DECL_ACCESSORS(sec, Object)
// [cache stamp]: sample of the date cache stamp at the
// moment when local fields were cached.
DECL_ACCESSORS(cache_stamp, Object)
// Casting.
static inline JSDate* cast(Object* obj);
// Returns the date field with the specified index.
// See FieldIndex for the list of date fields.
static Object* GetField(Object* date, Smi* index);
void SetValue(Object* value, bool is_value_nan);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSDatePrint() {
JSDatePrint(stdout);
}
void JSDatePrint(FILE* out);
#endif
DECLARE_VERIFIER(JSDate)
// The order is important. It must be kept in sync with date macros
// in macros.py.
enum FieldIndex {
kDateValue,
kYear,
kMonth,
kDay,
kWeekday,
kHour,
kMinute,
kSecond,
kFirstUncachedField,
kMillisecond = kFirstUncachedField,
kDays,
kTimeInDay,
kFirstUTCField,
kYearUTC = kFirstUTCField,
kMonthUTC,
kDayUTC,
kWeekdayUTC,
kHourUTC,
kMinuteUTC,
kSecondUTC,
kMillisecondUTC,
kDaysUTC,
kTimeInDayUTC,
kTimezoneOffset
};
// Layout description.
static const int kValueOffset = JSObject::kHeaderSize;
static const int kYearOffset = kValueOffset + kPointerSize;
static const int kMonthOffset = kYearOffset + kPointerSize;
static const int kDayOffset = kMonthOffset + kPointerSize;
static const int kWeekdayOffset = kDayOffset + kPointerSize;
static const int kHourOffset = kWeekdayOffset + kPointerSize;
static const int kMinOffset = kHourOffset + kPointerSize;
static const int kSecOffset = kMinOffset + kPointerSize;
static const int kCacheStampOffset = kSecOffset + kPointerSize;
static const int kSize = kCacheStampOffset + kPointerSize;
private:
inline Object* DoGetField(FieldIndex index);
Object* GetUTCField(FieldIndex index, double value, DateCache* date_cache);
// Computes and caches the cacheable fields of the date.
inline void SetLocalFields(int64_t local_time_ms, DateCache* date_cache);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSDate);
};
// Representation of message objects used for error reporting through
// the API. The messages are formatted in JavaScript so this object is
// a real JavaScript object. The information used for formatting the
// error messages are not directly accessible from JavaScript to
// prevent leaking information to user code called during error
// formatting.
class JSMessageObject: public JSObject {
public:
// [type]: the type of error message.
DECL_ACCESSORS(type, String)
// [arguments]: the arguments for formatting the error message.
DECL_ACCESSORS(arguments, JSArray)
// [script]: the script from which the error message originated.
DECL_ACCESSORS(script, Object)
// [stack_trace]: the stack trace for this error message.
DECL_ACCESSORS(stack_trace, Object)
// [stack_frames]: an array of stack frames for this error object.
DECL_ACCESSORS(stack_frames, Object)
// [start_position]: the start position in the script for the error message.
inline int start_position();
inline void set_start_position(int value);
// [end_position]: the end position in the script for the error message.
inline int end_position();
inline void set_end_position(int value);
// Casting.
static inline JSMessageObject* cast(Object* obj);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSMessageObjectPrint() {
JSMessageObjectPrint(stdout);
}
void JSMessageObjectPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSMessageObject)
// Layout description.
static const int kTypeOffset = JSObject::kHeaderSize;
static const int kArgumentsOffset = kTypeOffset + kPointerSize;
static const int kScriptOffset = kArgumentsOffset + kPointerSize;
static const int kStackTraceOffset = kScriptOffset + kPointerSize;
static const int kStackFramesOffset = kStackTraceOffset + kPointerSize;
static const int kStartPositionOffset = kStackFramesOffset + kPointerSize;
static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
static const int kSize = kEndPositionOffset + kPointerSize;
typedef FixedBodyDescriptor<HeapObject::kMapOffset,
kStackFramesOffset + kPointerSize,
kSize> BodyDescriptor;
};
// Regular expressions
// The regular expression holds a single reference to a FixedArray in
// the kDataOffset field.
// The FixedArray contains the following data:
// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
// - reference to the original source string
// - reference to the original flag string
// If it is an atom regexp
// - a reference to a literal string to search for
// If it is an irregexp regexp:
// - a reference to code for ASCII inputs (bytecode or compiled), or a smi
// used for tracking the last usage (used for code flushing).
// - a reference to code for UC16 inputs (bytecode or compiled), or a smi
// used for tracking the last usage (used for code flushing)..
// - max number of registers used by irregexp implementations.
// - number of capture registers (output values) of the regexp.
class JSRegExp: public JSObject {
public:
// Meaning of Type:
// NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
// ATOM: A simple string to match against using an indexOf operation.
// IRREGEXP: Compiled with Irregexp.
// IRREGEXP_NATIVE: Compiled to native code with Irregexp.
enum Type { NOT_COMPILED, ATOM, IRREGEXP };
enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
class Flags {
public:
explicit Flags(uint32_t value) : value_(value) { }
bool is_global() { return (value_ & GLOBAL) != 0; }
bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
bool is_multiline() { return (value_ & MULTILINE) != 0; }
uint32_t value() { return value_; }
private:
uint32_t value_;
};
DECL_ACCESSORS(data, Object)
inline Type TypeTag();
inline int CaptureCount();
inline Flags GetFlags();
inline String* Pattern();
inline Object* DataAt(int index);
// Set implementation data after the object has been prepared.
inline void SetDataAt(int index, Object* value);
// Used during GC when flushing code or setting age.
inline Object* DataAtUnchecked(int index);
inline void SetDataAtUnchecked(int index, Object* value, Heap* heap);
inline Type TypeTagUnchecked();
static int code_index(bool is_ascii) {
if (is_ascii) {
return kIrregexpASCIICodeIndex;
} else {
return kIrregexpUC16CodeIndex;
}
}
static int saved_code_index(bool is_ascii) {
if (is_ascii) {
return kIrregexpASCIICodeSavedIndex;
} else {
return kIrregexpUC16CodeSavedIndex;
}
}
static inline JSRegExp* cast(Object* obj);
// Dispatched behavior.
DECLARE_VERIFIER(JSRegExp)
static const int kDataOffset = JSObject::kHeaderSize;
static const int kSize = kDataOffset + kPointerSize;
// Indices in the data array.
static const int kTagIndex = 0;
static const int kSourceIndex = kTagIndex + 1;
static const int kFlagsIndex = kSourceIndex + 1;
static const int kDataIndex = kFlagsIndex + 1;
// The data fields are used in different ways depending on the
// value of the tag.
// Atom regexps (literal strings).
static const int kAtomPatternIndex = kDataIndex;
static const int kAtomDataSize = kAtomPatternIndex + 1;
// Irregexp compiled code or bytecode for ASCII. If compilation
// fails, this fields hold an exception object that should be
// thrown if the regexp is used again.
static const int kIrregexpASCIICodeIndex = kDataIndex;
// Irregexp compiled code or bytecode for UC16. If compilation
// fails, this fields hold an exception object that should be
// thrown if the regexp is used again.
static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
// Saved instance of Irregexp compiled code or bytecode for ASCII that
// is a potential candidate for flushing.
static const int kIrregexpASCIICodeSavedIndex = kDataIndex + 2;
// Saved instance of Irregexp compiled code or bytecode for UC16 that is
// a potential candidate for flushing.
static const int kIrregexpUC16CodeSavedIndex = kDataIndex + 3;
// Maximal number of registers used by either ASCII or UC16.
// Only used to check that there is enough stack space
static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 4;
// Number of captures in the compiled regexp.
static const int kIrregexpCaptureCountIndex = kDataIndex + 5;
static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
// Offsets directly into the data fixed array.
static const int kDataTagOffset =
FixedArray::kHeaderSize + kTagIndex * kPointerSize;
static const int kDataAsciiCodeOffset =
FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize;
static const int kDataUC16CodeOffset =
FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
static const int kIrregexpCaptureCountOffset =
FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
// In-object fields.
static const int kSourceFieldIndex = 0;
static const int kGlobalFieldIndex = 1;
static const int kIgnoreCaseFieldIndex = 2;
static const int kMultilineFieldIndex = 3;
static const int kLastIndexFieldIndex = 4;
static const int kInObjectFieldCount = 5;
// The uninitialized value for a regexp code object.
static const int kUninitializedValue = -1;
// The compilation error value for the regexp code object. The real error
// object is in the saved code field.
static const int kCompilationErrorValue = -2;
// When we store the sweep generation at which we moved the code from the
// code index to the saved code index we mask it of to be in the [0:255]
// range.
static const int kCodeAgeMask = 0xff;
};
class CompilationCacheShape : public BaseShape<HashTableKey*> {
public:
static inline bool IsMatch(HashTableKey* key, Object* value) {
return key->IsMatch(value);
}
static inline uint32_t Hash(HashTableKey* key) {
return key->Hash();
}
static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
return key->HashForObject(object);
}
MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
return key->AsObject();
}
static const int kPrefixSize = 0;
static const int kEntrySize = 2;
};
class CompilationCacheTable: public HashTable<CompilationCacheShape,
HashTableKey*> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(String* src, Context* context);
Object* LookupEval(String* src,
Context* context,
LanguageMode language_mode,
int scope_position);
Object* LookupRegExp(String* source, JSRegExp::Flags flags);
MUST_USE_RESULT MaybeObject* Put(String* src,
Context* context,
Object* value);
MUST_USE_RESULT MaybeObject* PutEval(String* src,
Context* context,
SharedFunctionInfo* value,
int scope_position);
MUST_USE_RESULT MaybeObject* PutRegExp(String* src,
JSRegExp::Flags flags,
FixedArray* value);
// Remove given value from cache.
void Remove(Object* value);
static inline CompilationCacheTable* cast(Object* obj);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
};
class CodeCache: public Struct {
public:
DECL_ACCESSORS(default_cache, FixedArray)
DECL_ACCESSORS(normal_type_cache, Object)
// Add the code object to the cache.
MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
// Lookup code object in the cache. Returns code object if found and undefined
// if not.
Object* Lookup(String* name, Code::Flags flags);
// Get the internal index of a code object in the cache. Returns -1 if the
// code object is not in that cache. This index can be used to later call
// RemoveByIndex. The cache cannot be modified between a call to GetIndex and
// RemoveByIndex.
int GetIndex(Object* name, Code* code);
// Remove an object from the cache with the provided internal index.
void RemoveByIndex(Object* name, Code* code, int index);
static inline CodeCache* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void CodeCachePrint() {
CodeCachePrint(stdout);
}
void CodeCachePrint(FILE* out);
#endif
DECLARE_VERIFIER(CodeCache)
static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
static const int kNormalTypeCacheOffset =
kDefaultCacheOffset + kPointerSize;
static const int kSize = kNormalTypeCacheOffset + kPointerSize;
private:
MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
Object* LookupDefaultCache(String* name, Code::Flags flags);
Object* LookupNormalTypeCache(String* name, Code::Flags flags);
// Code cache layout of the default cache. Elements are alternating name and
// code objects for non normal load/store/call IC's.
static const int kCodeCacheEntrySize = 2;
static const int kCodeCacheEntryNameOffset = 0;
static const int kCodeCacheEntryCodeOffset = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
};
class CodeCacheHashTableShape : public BaseShape<HashTableKey*> {
public:
static inline bool IsMatch(HashTableKey* key, Object* value) {
return key->IsMatch(value);
}
static inline uint32_t Hash(HashTableKey* key) {
return key->Hash();
}
static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
return key->HashForObject(object);
}
MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
return key->AsObject();
}
static const int kPrefixSize = 0;
static const int kEntrySize = 2;
};
class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
HashTableKey*> {
public:
Object* Lookup(String* name, Code::Flags flags);
MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
int GetIndex(String* name, Code::Flags flags);
void RemoveByIndex(int index);
static inline CodeCacheHashTable* cast(Object* obj);
// Initial size of the fixed array backing the hash table.
static const int kInitialSize = 64;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
};
class PolymorphicCodeCache: public Struct {
public:
DECL_ACCESSORS(cache, Object)
static void Update(Handle<PolymorphicCodeCache> cache,
MapHandleList* maps,
Code::Flags flags,
Handle<Code> code);
MUST_USE_RESULT MaybeObject* Update(MapHandleList* maps,
Code::Flags flags,
Code* code);
// Returns an undefined value if the entry is not found.
Handle<Object> Lookup(MapHandleList* maps, Code::Flags flags);
static inline PolymorphicCodeCache* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void PolymorphicCodeCachePrint() {
PolymorphicCodeCachePrint(stdout);
}
void PolymorphicCodeCachePrint(FILE* out);
#endif
DECLARE_VERIFIER(PolymorphicCodeCache)
static const int kCacheOffset = HeapObject::kHeaderSize;
static const int kSize = kCacheOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCache);
};
class PolymorphicCodeCacheHashTable
: public HashTable<CodeCacheHashTableShape, HashTableKey*> {
public:
Object* Lookup(MapHandleList* maps, int code_kind);
MUST_USE_RESULT MaybeObject* Put(MapHandleList* maps,
int code_kind,
Code* code);
static inline PolymorphicCodeCacheHashTable* cast(Object* obj);
static const int kInitialSize = 64;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCacheHashTable);
};
class TypeFeedbackInfo: public Struct {
public:
inline int ic_total_count();
inline void set_ic_total_count(int count);
inline int ic_with_type_info_count();
inline void change_ic_with_type_info_count(int count);
inline void initialize_storage();
inline void change_own_type_change_checksum();
inline int own_type_change_checksum();
inline void set_inlined_type_change_checksum(int checksum);
inline bool matches_inlined_type_change_checksum(int checksum);
DECL_ACCESSORS(type_feedback_cells, TypeFeedbackCells)
static inline TypeFeedbackInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void TypeFeedbackInfoPrint() {
TypeFeedbackInfoPrint(stdout);
}
void TypeFeedbackInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(TypeFeedbackInfo)
static const int kStorage1Offset = HeapObject::kHeaderSize;
static const int kStorage2Offset = kStorage1Offset + kPointerSize;
static const int kTypeFeedbackCellsOffset = kStorage2Offset + kPointerSize;
static const int kSize = kTypeFeedbackCellsOffset + kPointerSize;
private:
static const int kTypeChangeChecksumBits = 7;
class ICTotalCountField: public BitField<int, 0,
kSmiValueSize - kTypeChangeChecksumBits> {}; // NOLINT
class OwnTypeChangeChecksum: public BitField<int,
kSmiValueSize - kTypeChangeChecksumBits,
kTypeChangeChecksumBits> {}; // NOLINT
class ICsWithTypeInfoCountField: public BitField<int, 0,
kSmiValueSize - kTypeChangeChecksumBits> {}; // NOLINT
class InlinedTypeChangeChecksum: public BitField<int,
kSmiValueSize - kTypeChangeChecksumBits,
kTypeChangeChecksumBits> {}; // NOLINT
DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackInfo);
};
// Representation of a slow alias as part of a non-strict arguments objects.
// For fast aliases (if HasNonStrictArgumentsElements()):
// - the parameter map contains an index into the context
// - all attributes of the element have default values
// For slow aliases (if HasDictionaryArgumentsElements()):
// - the parameter map contains no fast alias mapping (i.e. the hole)
// - this struct (in the slow backing store) contains an index into the context
// - all attributes are available as part if the property details
class AliasedArgumentsEntry: public Struct {
public:
inline int aliased_context_slot();
inline void set_aliased_context_slot(int count);
static inline AliasedArgumentsEntry* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void AliasedArgumentsEntryPrint() {
AliasedArgumentsEntryPrint(stdout);
}
void AliasedArgumentsEntryPrint(FILE* out);
#endif
DECLARE_VERIFIER(AliasedArgumentsEntry)
static const int kAliasedContextSlot = HeapObject::kHeaderSize;
static const int kSize = kAliasedContextSlot + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AliasedArgumentsEntry);
};
enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
class StringHasher {
public:
explicit inline StringHasher(int length, uint32_t seed);
// Returns true if the hash of this string can be computed without
// looking at the contents.
inline bool has_trivial_hash();
// Add a character to the hash and update the array index calculation.
inline void AddCharacter(uint32_t c);
// Adds a character to the hash but does not update the array index
// calculation. This can only be called when it has been verified
// that the input is not an array index.
inline void AddCharacterNoIndex(uint32_t c);
// Add a character above 0xffff as a surrogate pair. These can get into
// the hasher through the routines that take a UTF-8 string and make a symbol.
void AddSurrogatePair(uc32 c);
void AddSurrogatePairNoIndex(uc32 c);
// Returns the value to store in the hash field of a string with
// the given length and contents.
uint32_t GetHashField();
// Returns true if the characters seen so far make up a legal array
// index.
bool is_array_index() { return is_array_index_; }
// Calculated hash value for a string consisting of 1 to
// String::kMaxArrayIndexSize digits with no leading zeros (except "0").
// value is represented decimal value.
static uint32_t MakeArrayIndexHash(uint32_t value, int length);
// No string is allowed to have a hash of zero. That value is reserved
// for internal properties. If the hash calculation yields zero then we
// use 27 instead.
static const int kZeroHash = 27;
private:
uint32_t array_index() {
ASSERT(is_array_index());
return array_index_;
}
inline uint32_t GetHash();
// Reusable parts of the hashing algorithm.
INLINE(static uint32_t AddCharacterCore(uint32_t running_hash, uint32_t c));
INLINE(static uint32_t GetHashCore(uint32_t running_hash));
int length_;
uint32_t raw_running_hash_;
uint32_t array_index_;
bool is_array_index_;
bool is_first_char_;
friend class TwoCharHashTableKey;
template <bool seq_ascii> friend class JsonParser;
};
class IncrementalAsciiStringHasher {
public:
explicit inline IncrementalAsciiStringHasher(uint32_t seed, char first_char);
inline void AddCharacter(uc32 c);
inline uint32_t GetHash();
private:
int length_;
uint32_t raw_running_hash_;
uint32_t array_index_;
bool is_array_index_;
char first_char_;
};
// Calculates string hash.
template <typename schar>
inline uint32_t HashSequentialString(const schar* chars,
int length,
uint32_t seed);
// The characteristics of a string are stored in its map. Retrieving these
// few bits of information is moderately expensive, involving two memory
// loads where the second is dependent on the first. To improve efficiency
// the shape of the string is given its own class so that it can be retrieved
// once and used for several string operations. A StringShape is small enough
// to be passed by value and is immutable, but be aware that flattening a
// string can potentially alter its shape. Also be aware that a GC caused by
// something else can alter the shape of a string due to ConsString
// shortcutting. Keeping these restrictions in mind has proven to be error-
// prone and so we no longer put StringShapes in variables unless there is a
// concrete performance benefit at that particular point in the code.
class StringShape BASE_EMBEDDED {
public:
inline explicit StringShape(String* s);
inline explicit StringShape(Map* s);
inline explicit StringShape(InstanceType t);
inline bool IsSequential();
inline bool IsExternal();
inline bool IsCons();
inline bool IsSliced();
inline bool IsIndirect();
inline bool IsExternalAscii();
inline bool IsExternalTwoByte();
inline bool IsSequentialAscii();
inline bool IsSequentialTwoByte();
inline bool IsSymbol();
inline StringRepresentationTag representation_tag();
inline uint32_t encoding_tag();
inline uint32_t full_representation_tag();
inline uint32_t size_tag();
#ifdef DEBUG
inline uint32_t type() { return type_; }
inline void invalidate() { valid_ = false; }
inline bool valid() { return valid_; }
#else
inline void invalidate() { }
#endif
private:
uint32_t type_;
#ifdef DEBUG
inline void set_valid() { valid_ = true; }
bool valid_;
#else
inline void set_valid() { }
#endif
};
// The String abstract class captures JavaScript string values:
//
// Ecma-262:
// 4.3.16 String Value
// A string value is a member of the type String and is a finite
// ordered sequence of zero or more 16-bit unsigned integer values.
//
// All string values have a length field.
class String: public HeapObject {
public:
// Representation of the flat content of a String.
// A non-flat string doesn't have flat content.
// A flat string has content that's encoded as a sequence of either
// ASCII chars or two-byte UC16.
// Returned by String::GetFlatContent().
class FlatContent {
public:
// Returns true if the string is flat and this structure contains content.
bool IsFlat() { return state_ != NON_FLAT; }
// Returns true if the structure contains ASCII content.
bool IsAscii() { return state_ == ASCII; }
// Returns true if the structure contains two-byte content.
bool IsTwoByte() { return state_ == TWO_BYTE; }
// Return the ASCII content of the string. Only use if IsAscii() returns
// true.
Vector<const char> ToAsciiVector() {
ASSERT_EQ(ASCII, state_);
return Vector<const char>::cast(buffer_);
}
// Return the two-byte content of the string. Only use if IsTwoByte()
// returns true.
Vector<const uc16> ToUC16Vector() {
ASSERT_EQ(TWO_BYTE, state_);
return Vector<const uc16>::cast(buffer_);
}
private:
enum State { NON_FLAT, ASCII, TWO_BYTE };
// Constructors only used by String::GetFlatContent().
explicit FlatContent(Vector<const char> chars)
: buffer_(Vector<const byte>::cast(chars)),
state_(ASCII) { }
explicit FlatContent(Vector<const uc16> chars)
: buffer_(Vector<const byte>::cast(chars)),
state_(TWO_BYTE) { }
FlatContent() : buffer_(), state_(NON_FLAT) { }
Vector<const byte> buffer_;
State state_;
friend class String;
};
// Get and set the length of the string.
inline int length();
inline void set_length(int value);
// Get and set the hash field of the string.
inline uint32_t hash_field();
inline void set_hash_field(uint32_t value);
// Returns whether this string has only ASCII chars, i.e. all of them can
// be ASCII encoded. This might be the case even if the string is
// two-byte. Such strings may appear when the embedder prefers
// two-byte external representations even for ASCII data.
inline bool IsAsciiRepresentation();
inline bool IsTwoByteRepresentation();
// Cons and slices have an encoding flag that may not represent the actual
// encoding of the underlying string. This is taken into account here.
// Requires: this->IsFlat()
inline bool IsAsciiRepresentationUnderneath();
inline bool IsTwoByteRepresentationUnderneath();
// NOTE: this should be considered only a hint. False negatives are
// possible.
inline bool HasOnlyAsciiChars();
// Get and set individual two byte chars in the string.
inline void Set(int index, uint16_t value);
// Get individual two byte char in the string. Repeated calls
// to this method are not efficient unless the string is flat.
INLINE(uint16_t Get(int index));
// Try to flatten the string. Checks first inline to see if it is
// necessary. Does nothing if the string is not a cons string.
// Flattening allocates a sequential string with the same data as
// the given string and mutates the cons string to a degenerate
// form, where the first component is the new sequential string and
// the second component is the empty string. If allocation fails,
// this function returns a failure. If flattening succeeds, this
// function returns the sequential string that is now the first
// component of the cons string.
//
// Degenerate cons strings are handled specially by the garbage
// collector (see IsShortcutCandidate).
//
// Use FlattenString from Handles.cc to flatten even in case an
// allocation failure happens.
inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
// Convenience function. Has exactly the same behavior as
// TryFlatten(), except in the case of failure returns the original
// string.
inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
// Tries to return the content of a flat string as a structure holding either
// a flat vector of char or of uc16.
// If the string isn't flat, and therefore doesn't have flat content, the
// returned structure will report so, and can't provide a vector of either
// kind.
FlatContent GetFlatContent();
// Returns the parent of a sliced string or first part of a flat cons string.
// Requires: StringShape(this).IsIndirect() && this->IsFlat()
inline String* GetUnderlying();
// Mark the string as an undetectable object. It only applies to
// ASCII and two byte string types.
bool MarkAsUndetectable();
// Return a substring.
MUST_USE_RESULT MaybeObject* SubString(int from,
int to,
PretenureFlag pretenure = NOT_TENURED);
// String equality operations.
inline bool Equals(String* other);
bool IsEqualTo(Vector<const char> str);
bool IsAsciiEqualTo(Vector<const char> str);
bool IsTwoByteEqualTo(Vector<const uc16> str);
// Return a UTF8 representation of the string. The string is null
// terminated but may optionally contain nulls. Length is returned
// in length_output if length_output is not a null pointer The string
// should be nearly flat, otherwise the performance of this method may
// be very slow (quadratic in the length). Setting robustness_flag to
// ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
// handles unexpected data without causing assert failures and it does not
// do any heap allocations. This is useful when printing stack traces.
SmartArrayPointer<char> ToCString(AllowNullsFlag allow_nulls,
RobustnessFlag robustness_flag,
int offset,
int length,
int* length_output = 0);
SmartArrayPointer<char> ToCString(
AllowNullsFlag allow_nulls = DISALLOW_NULLS,
RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
int* length_output = 0);
// Return a 16 bit Unicode representation of the string.
// The string should be nearly flat, otherwise the performance of
// of this method may be very bad. Setting robustness_flag to
// ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
// handles unexpected data without causing assert failures and it does not
// do any heap allocations. This is useful when printing stack traces.
SmartArrayPointer<uc16> ToWideCString(
RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
// Tells whether the hash code has been computed.
inline bool HasHashCode();
// Returns a hash value used for the property table
inline uint32_t Hash();
static uint32_t ComputeHashField(unibrow::CharacterStream* buffer,
int length,
uint32_t seed);
static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
uint32_t* index,
int length);
// Externalization.
bool MakeExternal(v8::String::ExternalStringResource* resource);
bool MakeExternal(v8::String::ExternalAsciiStringResource* resource);
// Conversion.
inline bool AsArrayIndex(uint32_t* index);
// Casting.
static inline String* cast(Object* obj);
void PrintOn(FILE* out);
// For use during stack traces. Performs rudimentary sanity check.
bool LooksValid();
// Dispatched behavior.
void StringShortPrint(StringStream* accumulator);
#ifdef OBJECT_PRINT
inline void StringPrint() {
StringPrint(stdout);
}
void StringPrint(FILE* out);
char* ToAsciiArray();
#endif
DECLARE_VERIFIER(String)
inline bool IsFlat();
// Layout description.
static const int kLengthOffset = HeapObject::kHeaderSize;
static const int kHashFieldSlot = kLengthOffset + kPointerSize;
#if __BYTE_ORDER == __LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
static const int kHashFieldOffset = kHashFieldSlot;
#else
static const int kHashFieldOffset = kHashFieldSlot + kIntSize;
#endif
static const int kSize = kHashFieldSlot + kPointerSize;
// Maximum number of characters to consider when trying to convert a string
// value into an array index.
static const int kMaxArrayIndexSize = 10;
// Max ASCII char code.
static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
static const int kMaxUtf16CodeUnit = 0xffff;
// Mask constant for checking if a string has a computed hash code
// and if it is an array index. The least significant bit indicates
// whether a hash code has been computed. If the hash code has been
// computed the 2nd bit tells whether the string can be used as an
// array index.
static const int kHashNotComputedMask = 1;
static const int kIsNotArrayIndexMask = 1 << 1;
static const int kNofHashBitFields = 2;
// Shift constant retrieving hash code from hash field.
static const int kHashShift = kNofHashBitFields;
// Only these bits are relevant in the hash, since the top two are shifted
// out.
static const uint32_t kHashBitMask = 0xffffffffu >> kHashShift;
// Array index strings this short can keep their index in the hash
// field.
static const int kMaxCachedArrayIndexLength = 7;
// For strings which are array indexes the hash value has the string length
// mixed into the hash, mainly to avoid a hash value of zero which would be
// the case for the string '0'. 24 bits are used for the array index value.
static const int kArrayIndexValueBits = 24;
static const int kArrayIndexLengthBits =
kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
STATIC_CHECK((kArrayIndexLengthBits > 0));
STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
static const int kArrayIndexHashLengthShift =
kArrayIndexValueBits + kNofHashBitFields;
static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
static const int kArrayIndexValueMask =
((1 << kArrayIndexValueBits) - 1) << kHashShift;
// Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
// could use a mask to test if the length of string is less than or equal to
// kMaxCachedArrayIndexLength.
STATIC_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
static const int kContainsCachedArrayIndexMask =
(~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
kIsNotArrayIndexMask;
// Value of empty hash field indicating that the hash is not computed.
static const int kEmptyHashField =
kIsNotArrayIndexMask | kHashNotComputedMask;
// Value of hash field containing computed hash equal to zero.
static const int kEmptyStringHash = kIsNotArrayIndexMask;
// Maximal string length.
static const int kMaxLength = (1 << (32 - 2)) - 1;
// Max length for computing hash. For strings longer than this limit the
// string length is used as the hash value.
static const int kMaxHashCalcLength = 16383;
// Limit for truncation in short printing.
static const int kMaxShortPrintLength = 1024;
// Support for regular expressions.
const uc16* GetTwoByteData();
const uc16* GetTwoByteData(unsigned start);
// Support for StringInputBuffer
static const unibrow::byte* ReadBlock(String* input,
unibrow::byte* util_buffer,
unsigned capacity,
unsigned* remaining,
unsigned* offset);
static const unibrow::byte* ReadBlock(String** input,
unibrow::byte* util_buffer,
unsigned capacity,
unsigned* remaining,
unsigned* offset);
// Helper function for flattening strings.
template <typename sinkchar>
static void WriteToFlat(String* source,
sinkchar* sink,
int from,
int to);
// The return value may point to the first aligned word containing the
// first non-ascii character, rather than directly to the non-ascii character.
// If the return value is >= the passed length, the entire string was ASCII.
static inline int NonAsciiStart(const char* chars, int length) {
const char* start = chars;
const char* limit = chars + length;
#ifdef V8_HOST_CAN_READ_UNALIGNED
ASSERT(kMaxAsciiCharCode == 0x7F);
const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
while (chars + sizeof(uintptr_t) <= limit) {
if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
return static_cast<int>(chars - start);
}
chars += sizeof(uintptr_t);
}
#endif
while (chars < limit) {
if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) {
return static_cast<int>(chars - start);
}
++chars;
}
return static_cast<int>(chars - start);
}
static inline bool IsAscii(const char* chars, int length) {
return NonAsciiStart(chars, length) >= length;
}
static inline int NonAsciiStart(const uc16* chars, int length) {
const uc16* limit = chars + length;
const uc16* start = chars;
while (chars < limit) {
if (*chars > kMaxAsciiCharCodeU) return static_cast<int>(chars - start);
++chars;
}
return static_cast<int>(chars - start);
}
static inline bool IsAscii(const uc16* chars, int length) {
return NonAsciiStart(chars, length) >= length;
}
protected:
class ReadBlockBuffer {
public:
ReadBlockBuffer(unibrow::byte* util_buffer_,
unsigned cursor_,
unsigned capacity_,
unsigned remaining_) :
util_buffer(util_buffer_),
cursor(cursor_),
capacity(capacity_),
remaining(remaining_) {
}
unibrow::byte* util_buffer;
unsigned cursor;
unsigned capacity;
unsigned remaining;
};
static inline const unibrow::byte* ReadBlock(String* input,
ReadBlockBuffer* buffer,
unsigned* offset,
unsigned max_chars);
static void ReadBlockIntoBuffer(String* input,
ReadBlockBuffer* buffer,
unsigned* offset_ptr,
unsigned max_chars);
private:
// Try to flatten the top level ConsString that is hiding behind this
// string. This is a no-op unless the string is a ConsString. Flatten
// mutates the ConsString and might return a failure.
MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
static inline bool IsHashFieldComputed(uint32_t field);
// Slow case of String::Equals. This implementation works on any strings
// but it is most efficient on strings that are almost flat.
bool SlowEquals(String* other);
// Slow case of AsArrayIndex.
bool SlowAsArrayIndex(uint32_t* index);
// Compute and set the hash code.
uint32_t ComputeAndSetHash();
DISALLOW_IMPLICIT_CONSTRUCTORS(String);
};
// The SeqString abstract class captures sequential string values.
class SeqString: public String {
public:
// Casting.
static inline SeqString* cast(Object* obj);
// Layout description.
static const int kHeaderSize = String::kSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
};
// The AsciiString class captures sequential ASCII string objects.
// Each character in the AsciiString is an ASCII character.
class SeqAsciiString: public SeqString {
public:
static const bool kHasAsciiEncoding = true;
// Dispatched behavior.
inline uint16_t SeqAsciiStringGet(int index);
inline void SeqAsciiStringSet(int index, uint16_t value);
// Get the address of the characters in this string.
inline Address GetCharsAddress();
inline char* GetChars();
// Casting
static inline SeqAsciiString* cast(Object* obj);
// Garbage collection support. This method is called by the
// garbage collector to compute the actual size of an AsciiString
// instance.
inline int SeqAsciiStringSize(InstanceType instance_type);
// Computes the size for an AsciiString instance of a given length.
static int SizeFor(int length) {
return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
}
// Maximal memory usage for a single sequential ASCII string.
static const int kMaxSize = 512 * MB - 1;
// Maximal length of a single sequential ASCII string.
// Q.v. String::kMaxLength which is the maximal size of concatenated strings.
static const int kMaxLength = (kMaxSize - kHeaderSize);
// Support for StringInputBuffer.
inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset,
unsigned chars);
inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
unsigned* offset,
unsigned chars);
DECLARE_VERIFIER(SeqAsciiString)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
};
// The TwoByteString class captures sequential unicode string objects.
// Each character in the TwoByteString is a two-byte uint16_t.
class SeqTwoByteString: public SeqString {
public:
static const bool kHasAsciiEncoding = false;
// Dispatched behavior.
inline uint16_t SeqTwoByteStringGet(int index);
inline void SeqTwoByteStringSet(int index, uint16_t value);
// Get the address of the characters in this string.
inline Address GetCharsAddress();
inline uc16* GetChars();
// For regexp code.
const uint16_t* SeqTwoByteStringGetData(unsigned start);
// Casting
static inline SeqTwoByteString* cast(Object* obj);
// Garbage collection support. This method is called by the
// garbage collector to compute the actual size of a TwoByteString
// instance.
inline int SeqTwoByteStringSize(InstanceType instance_type);
// Computes the size for a TwoByteString instance of a given length.
static int SizeFor(int length) {
return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
}
// Maximal memory usage for a single sequential two-byte string.
static const int kMaxSize = 512 * MB - 1;
// Maximal length of a single sequential two-byte string.
// Q.v. String::kMaxLength which is the maximal size of concatenated strings.
static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t);
// Support for StringInputBuffer.
inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset_ptr,
unsigned chars);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
};
// The ConsString class describes string values built by using the
// addition operator on strings. A ConsString is a pair where the
// first and second components are pointers to other string values.
// One or both components of a ConsString can be pointers to other
// ConsStrings, creating a binary tree of ConsStrings where the leaves
// are non-ConsString string values. The string value represented by
// a ConsString can be obtained by concatenating the leaf string
// values in a left-to-right depth-first traversal of the tree.
class ConsString: public String {
public:
// First string of the cons cell.
inline String* first();
// Doesn't check that the result is a string, even in debug mode. This is
// useful during GC where the mark bits confuse the checks.
inline Object* unchecked_first();
inline void set_first(String* first,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Second string of the cons cell.
inline String* second();
// Doesn't check that the result is a string, even in debug mode. This is
// useful during GC where the mark bits confuse the checks.
inline Object* unchecked_second();
inline void set_second(String* second,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Dispatched behavior.
uint16_t ConsStringGet(int index);
// Casting.
static inline ConsString* cast(Object* obj);
// Layout description.
static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
static const int kSecondOffset = kFirstOffset + kPointerSize;
static const int kSize = kSecondOffset + kPointerSize;
// Support for StringInputBuffer.
inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer,
unsigned* offset_ptr,
unsigned chars);
inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset_ptr,
unsigned chars);
// Minimum length for a cons string.
static const int kMinLength = 13;
typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
BodyDescriptor;
DECLARE_VERIFIER(ConsString)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
};
// The Sliced String class describes strings that are substrings of another
// sequential string. The motivation is to save time and memory when creating
// a substring. A Sliced String is described as a pointer to the parent,
// the offset from the start of the parent string and the length. Using
// a Sliced String therefore requires unpacking of the parent string and
// adding the offset to the start address. A substring of a Sliced String
// are not nested since the double indirection is simplified when creating
// such a substring.
// Currently missing features are:
// - handling externalized parent strings
// - external strings as parent
// - truncating sliced string to enable otherwise unneeded parent to be GC'ed.
class SlicedString: public String {
public:
inline String* parent();
inline void set_parent(String* parent,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline int offset();
inline void set_offset(int offset);
// Dispatched behavior.
uint16_t SlicedStringGet(int index);
// Casting.
static inline SlicedString* cast(Object* obj);
// Layout description.
static const int kParentOffset = POINTER_SIZE_ALIGN(String::kSize);
static const int kOffsetOffset = kParentOffset + kPointerSize;
static const int kSize = kOffsetOffset + kPointerSize;
// Support for StringInputBuffer
inline const unibrow::byte* SlicedStringReadBlock(ReadBlockBuffer* buffer,
unsigned* offset_ptr,
unsigned chars);
inline void SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset_ptr,
unsigned chars);
// Minimum length for a sliced string.
static const int kMinLength = 13;
typedef FixedBodyDescriptor<kParentOffset,
kOffsetOffset + kPointerSize, kSize>
BodyDescriptor;
DECLARE_VERIFIER(SlicedString)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SlicedString);
};
// The ExternalString class describes string values that are backed by
// a string resource that lies outside the V8 heap. ExternalStrings
// consist of the length field common to all strings, a pointer to the
// external resource. It is important to ensure (externally) that the
// resource is not deallocated while the ExternalString is live in the
// V8 heap.
//
// The API expects that all ExternalStrings are created through the
// API. Therefore, ExternalStrings should not be used internally.
class ExternalString: public String {
public:
// Casting
static inline ExternalString* cast(Object* obj);
// Layout description.
static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
static const int kShortSize = kResourceOffset + kPointerSize;
static const int kResourceDataOffset = kResourceOffset + kPointerSize;
static const int kSize = kResourceDataOffset + kPointerSize;
// Return whether external string is short (data pointer is not cached).
inline bool is_short();
STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
};
// The ExternalAsciiString class is an external string backed by an
// ASCII string.
class ExternalAsciiString: public ExternalString {
public:
static const bool kHasAsciiEncoding = true;
typedef v8::String::ExternalAsciiStringResource Resource;
// The underlying resource.
inline const Resource* resource();
inline void set_resource(const Resource* buffer);
// Update the pointer cache to the external character array.
// The cached pointer is always valid, as the external character array does =
// not move during lifetime. Deserialization is the only exception, after
// which the pointer cache has to be refreshed.
inline void update_data_cache();
inline const char* GetChars();
// Dispatched behavior.
inline uint16_t ExternalAsciiStringGet(int index);
// Casting.
static inline ExternalAsciiString* cast(Object* obj);
// Garbage collection support.
inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
template<typename StaticVisitor>
inline void ExternalAsciiStringIterateBody();
// Support for StringInputBuffer.
const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
unsigned* offset,
unsigned chars);
inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset,
unsigned chars);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString);
};
// The ExternalTwoByteString class is an external string backed by a UTF-16
// encoded string.
class ExternalTwoByteString: public ExternalString {
public:
static const bool kHasAsciiEncoding = false;
typedef v8::String::ExternalStringResource Resource;
// The underlying string resource.
inline const Resource* resource();
inline void set_resource(const Resource* buffer);
// Update the pointer cache to the external character array.
// The cached pointer is always valid, as the external character array does =
// not move during lifetime. Deserialization is the only exception, after
// which the pointer cache has to be refreshed.
inline void update_data_cache();
inline const uint16_t* GetChars();
// Dispatched behavior.
inline uint16_t ExternalTwoByteStringGet(int index);
// For regexp code.
inline const uint16_t* ExternalTwoByteStringGetData(unsigned start);
// Casting.
static inline ExternalTwoByteString* cast(Object* obj);
// Garbage collection support.
inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
template<typename StaticVisitor>
inline void ExternalTwoByteStringIterateBody();
// Support for StringInputBuffer.
void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset_ptr,
unsigned chars);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
};
// Utility superclass for stack-allocated objects that must be updated
// on gc. It provides two ways for the gc to update instances, either
// iterating or updating after gc.
class Relocatable BASE_EMBEDDED {
public:
explicit inline Relocatable(Isolate* isolate);
inline virtual ~Relocatable();
virtual void IterateInstance(ObjectVisitor* v) { }
virtual void PostGarbageCollection() { }
static void PostGarbageCollectionProcessing();
static int ArchiveSpacePerThread();
static char* ArchiveState(Isolate* isolate, char* to);
static char* RestoreState(Isolate* isolate, char* from);
static void Iterate(ObjectVisitor* v);
static void Iterate(ObjectVisitor* v, Relocatable* top);
static char* Iterate(ObjectVisitor* v, char* t);
private:
Isolate* isolate_;
Relocatable* prev_;
};
// A flat string reader provides random access to the contents of a
// string independent of the character width of the string. The handle
// must be valid as long as the reader is being used.
class FlatStringReader : public Relocatable {
public:
FlatStringReader(Isolate* isolate, Handle<String> str);
FlatStringReader(Isolate* isolate, Vector<const char> input);
void PostGarbageCollection();
inline uc32 Get(int index);
int length() { return length_; }
private:
String** str_;
bool is_ascii_;
int length_;
const void* start_;
};
// Note that StringInputBuffers are not valid across a GC! To fix this
// it would have to store a String Handle instead of a String* and
// AsciiStringReadBlock would have to be modified to use memcpy.
//
// StringInputBuffer is able to traverse any string regardless of how
// deeply nested a sequence of ConsStrings it is made of. However,
// performance will be better if deep strings are flattened before they
// are traversed. Since flattening requires memory allocation this is
// not always desirable, however (esp. in debugging situations).
class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> {
public:
virtual void Seek(unsigned pos);
inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {}
explicit inline StringInputBuffer(String* backing):
unibrow::InputBuffer<String, String*, 1024>(backing) {}
};
class SafeStringInputBuffer
: public unibrow::InputBuffer<String, String**, 256> {
public:
virtual void Seek(unsigned pos);
inline SafeStringInputBuffer()
: unibrow::InputBuffer<String, String**, 256>() {}
explicit inline SafeStringInputBuffer(String** backing)
: unibrow::InputBuffer<String, String**, 256>(backing) {}
};
template <typename T>
class VectorIterator {
public:
VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
T GetNext() { return data_[index_++]; }
bool has_more() { return index_ < data_.length(); }
private:
Vector<const T> data_;
int index_;
};
// The Oddball describes objects null, undefined, true, and false.
class Oddball: public HeapObject {
public:
// [to_string]: Cached to_string computed at startup.
DECL_ACCESSORS(to_string, String)
// [to_number]: Cached to_number computed at startup.
DECL_ACCESSORS(to_number, Object)
inline byte kind();
inline void set_kind(byte kind);
// Casting.
static inline Oddball* cast(Object* obj);
// Dispatched behavior.
DECLARE_VERIFIER(Oddball)
// Initialize the fields.
MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
Object* to_number,
byte kind);
// Layout description.
static const int kToStringOffset = HeapObject::kHeaderSize;
static const int kToNumberOffset = kToStringOffset + kPointerSize;
static const int kKindOffset = kToNumberOffset + kPointerSize;
static const int kSize = kKindOffset + kPointerSize;
static const byte kFalse = 0;
static const byte kTrue = 1;
static const byte kNotBooleanMask = ~1;
static const byte kTheHole = 2;
static const byte kNull = 3;
static const byte kArgumentMarker = 4;
static const byte kUndefined = 5;
static const byte kOther = 6;
typedef FixedBodyDescriptor<kToStringOffset,
kToNumberOffset + kPointerSize,
kSize> BodyDescriptor;
STATIC_CHECK(kKindOffset == Internals::kOddballKindOffset);
STATIC_CHECK(kNull == Internals::kNullOddballKind);
STATIC_CHECK(kUndefined == Internals::kUndefinedOddballKind);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
};
class JSGlobalPropertyCell: public HeapObject {
public:
// [value]: value of the global property.
DECL_ACCESSORS(value, Object)
// Casting.
static inline JSGlobalPropertyCell* cast(Object* obj);
static inline JSGlobalPropertyCell* FromValueAddress(Address value) {
return cast(FromAddress(value - kValueOffset));
}
inline Address ValueAddress() {
return address() + kValueOffset;
}
DECLARE_VERIFIER(JSGlobalPropertyCell)
#ifdef OBJECT_PRINT
inline void JSGlobalPropertyCellPrint() {
JSGlobalPropertyCellPrint(stdout);
}
void JSGlobalPropertyCellPrint(FILE* out);
#endif
// Layout description.
static const int kValueOffset = HeapObject::kHeaderSize;
static const int kSize = kValueOffset + kPointerSize;
typedef FixedBodyDescriptor<kValueOffset,
kValueOffset + kPointerSize,
kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
};
// The JSProxy describes EcmaScript Harmony proxies
class JSProxy: public JSReceiver {
public:
// [handler]: The handler property.
DECL_ACCESSORS(handler, Object)
// [hash]: The hash code property (undefined if not initialized yet).
DECL_ACCESSORS(hash, Object)
// Casting.
static inline JSProxy* cast(Object* obj);
bool HasPropertyWithHandler(String* name);
bool HasElementWithHandler(uint32_t index);
MUST_USE_RESULT MaybeObject* GetPropertyWithHandler(
Object* receiver,
String* name);
MUST_USE_RESULT MaybeObject* GetElementWithHandler(
Object* receiver,
uint32_t index);
MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
JSReceiver* receiver,
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetElementWithHandler(
JSReceiver* receiver,
uint32_t index,
Object* value,
StrictModeFlag strict_mode);
// If the handler defines an accessor property with a setter, invoke it.
// If it defines an accessor property without a setter, or a data property
// that is read-only, throw. In all these cases set '*done' to true,
// otherwise set it to false.
MUST_USE_RESULT MaybeObject* SetPropertyViaPrototypesWithHandler(
JSReceiver* receiver,
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool* done);
MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
String* name,
DeleteMode mode);
MUST_USE_RESULT MaybeObject* DeleteElementWithHandler(
uint32_t index,
DeleteMode mode);
MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
JSReceiver* receiver,
String* name);
MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler(
JSReceiver* receiver,
uint32_t index);
MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
// Turn this into an (empty) JSObject.
void Fix();
// Initializes the body after the handler slot.
inline void InitializeBody(int object_size, Object* value);
// Invoke a trap by name. If the trap does not exist on this's handler,
// but derived_trap is non-NULL, invoke that instead. May cause GC.
Handle<Object> CallTrap(const char* name,
Handle<Object> derived_trap,
int argc,
Handle<Object> args[]);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSProxyPrint() {
JSProxyPrint(stdout);
}
void JSProxyPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSProxy)
// Layout description. We add padding so that a proxy has the same
// size as a virgin JSObject. This is essential for becoming a JSObject
// upon freeze.
static const int kHandlerOffset = HeapObject::kHeaderSize;
static const int kHashOffset = kHandlerOffset + kPointerSize;
static const int kPaddingOffset = kHashOffset + kPointerSize;
static const int kSize = JSObject::kHeaderSize;
static const int kHeaderSize = kPaddingOffset;
static const int kPaddingSize = kSize - kPaddingOffset;
STATIC_CHECK(kPaddingSize >= 0);
typedef FixedBodyDescriptor<kHandlerOffset,
kPaddingOffset,
kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy);
};
class JSFunctionProxy: public JSProxy {
public:
// [call_trap]: The call trap.
DECL_ACCESSORS(call_trap, Object)
// [construct_trap]: The construct trap.
DECL_ACCESSORS(construct_trap, Object)
// Casting.
static inline JSFunctionProxy* cast(Object* obj);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSFunctionProxyPrint() {
JSFunctionProxyPrint(stdout);
}
void JSFunctionProxyPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSFunctionProxy)
// Layout description.
static const int kCallTrapOffset = JSProxy::kPaddingOffset;
static const int kConstructTrapOffset = kCallTrapOffset + kPointerSize;
static const int kPaddingOffset = kConstructTrapOffset + kPointerSize;
static const int kSize = JSFunction::kSize;
static const int kPaddingSize = kSize - kPaddingOffset;
STATIC_CHECK(kPaddingSize >= 0);
typedef FixedBodyDescriptor<kHandlerOffset,
kConstructTrapOffset + kPointerSize,
kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunctionProxy);
};
// The JSSet describes EcmaScript Harmony sets
class JSSet: public JSObject {
public:
// [set]: the backing hash set containing keys.
DECL_ACCESSORS(table, Object)
// Casting.
static inline JSSet* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void JSSetPrint() {
JSSetPrint(stdout);
}
void JSSetPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSSet)
static const int kTableOffset = JSObject::kHeaderSize;
static const int kSize = kTableOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSSet);
};
// The JSMap describes EcmaScript Harmony maps
class JSMap: public JSObject {
public:
// [table]: the backing hash table mapping keys to values.
DECL_ACCESSORS(table, Object)
// Casting.
static inline JSMap* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void JSMapPrint() {
JSMapPrint(stdout);
}
void JSMapPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSMap)
static const int kTableOffset = JSObject::kHeaderSize;
static const int kSize = kTableOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap);
};
// The JSWeakMap describes EcmaScript Harmony weak maps
class JSWeakMap: public JSObject {
public:
// [table]: the backing hash table mapping keys to values.
DECL_ACCESSORS(table, Object)
// [next]: linked list of encountered weak maps during GC.
DECL_ACCESSORS(next, Object)
// Casting.
static inline JSWeakMap* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void JSWeakMapPrint() {
JSWeakMapPrint(stdout);
}
void JSWeakMapPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSWeakMap)
static const int kTableOffset = JSObject::kHeaderSize;
static const int kNextOffset = kTableOffset + kPointerSize;
static const int kSize = kNextOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakMap);
};
// Foreign describes objects pointing from JavaScript to C structures.
// Since they cannot contain references to JS HeapObjects they can be
// placed in old_data_space.
class Foreign: public HeapObject {
public:
// [address]: field containing the address.
inline Address foreign_address();
inline void set_foreign_address(Address value);
// Casting.
static inline Foreign* cast(Object* obj);
// Dispatched behavior.
inline void ForeignIterateBody(ObjectVisitor* v);
template<typename StaticVisitor>
inline void ForeignIterateBody();
#ifdef OBJECT_PRINT
inline void ForeignPrint() {
ForeignPrint(stdout);
}
void ForeignPrint(FILE* out);
#endif
DECLARE_VERIFIER(Foreign)
// Layout description.
static const int kForeignAddressOffset = HeapObject::kHeaderSize;
static const int kSize = kForeignAddressOffset + kPointerSize;
STATIC_CHECK(kForeignAddressOffset == Internals::kForeignAddressOffset);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign);
};
// The JSArray describes JavaScript Arrays
// Such an array can be in one of two modes:
// - fast, backing storage is a FixedArray and length <= elements.length();
// Please note: push and pop can be used to grow and shrink the array.
// - slow, backing storage is a HashTable with numbers as keys.
class JSArray: public JSObject {
public:
// [length]: The length property.
DECL_ACCESSORS(length, Object)
// Overload the length setter to skip write barrier when the length
// is set to a smi. This matches the set function on FixedArray.
inline void set_length(Smi* length);
MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index,
Object* value);
// Initialize the array with the given capacity. The function may
// fail due to out-of-memory situations, but only if the requested
// capacity is non-zero.
MUST_USE_RESULT MaybeObject* Initialize(int capacity);
// Initializes the array to a certain length.
inline bool AllowsSetElementsLength();
MUST_USE_RESULT MaybeObject* SetElementsLength(Object* length);
// Set the content of the array to the content of storage.
MUST_USE_RESULT inline MaybeObject* SetContent(FixedArrayBase* storage);
// Casting.
static inline JSArray* cast(Object* obj);
// Uses handles. Ensures that the fixed array backing the JSArray has at
// least the stated size.
inline void EnsureSize(int minimum_size_of_backing_fixed_array);
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSArrayPrint() {
JSArrayPrint(stdout);
}
void JSArrayPrint(FILE* out);
#endif
DECLARE_VERIFIER(JSArray)
// Number of element slots to pre-allocate for an empty array.
static const int kPreallocatedArrayElements = 4;
// Layout description.
static const int kLengthOffset = JSObject::kHeaderSize;
static const int kSize = kLengthOffset + kPointerSize;
private:
// Expand the fixed array backing of a fast-case JSArray to at least
// the requested size.
void Expand(int minimum_size_of_backing_fixed_array);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
};
// JSRegExpResult is just a JSArray with a specific initial map.
// This initial map adds in-object properties for "index" and "input"
// properties, as assigned by RegExp.prototype.exec, which allows
// faster creation of RegExp exec results.
// This class just holds constants used when creating the result.
// After creation the result must be treated as a JSArray in all regards.
class JSRegExpResult: public JSArray {
public:
// Offsets of object fields.
static const int kIndexOffset = JSArray::kSize;
static const int kInputOffset = kIndexOffset + kPointerSize;
static const int kSize = kInputOffset + kPointerSize;
// Indices of in-object properties.
static const int kIndexIndex = 0;
static const int kInputIndex = 1;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
};
// An accessor must have a getter, but can have no setter.
//
// When setting a property, V8 searches accessors in prototypes.
// If an accessor was found and it does not have a setter,
// the request is ignored.
//
// If the accessor in the prototype has the READ_ONLY property attribute, then
// a new value is added to the local object when the property is set.
// This shadows the accessor in the prototype.
class AccessorInfo: public Struct {
public:
DECL_ACCESSORS(getter, Object)
DECL_ACCESSORS(setter, Object)
DECL_ACCESSORS(data, Object)
DECL_ACCESSORS(name, Object)
DECL_ACCESSORS(flag, Smi)
DECL_ACCESSORS(expected_receiver_type, Object)
inline bool all_can_read();
inline void set_all_can_read(bool value);
inline bool all_can_write();
inline void set_all_can_write(bool value);
inline bool prohibits_overwriting();
inline void set_prohibits_overwriting(bool value);
inline PropertyAttributes property_attributes();
inline void set_property_attributes(PropertyAttributes attributes);
// Checks whether the given receiver is compatible with this accessor.
inline bool IsCompatibleReceiver(Object* receiver);
static inline AccessorInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void AccessorInfoPrint() {
AccessorInfoPrint(stdout);
}
void AccessorInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(AccessorInfo)
static const int kGetterOffset = HeapObject::kHeaderSize;
static const int kSetterOffset = kGetterOffset + kPointerSize;
static const int kDataOffset = kSetterOffset + kPointerSize;
static const int kNameOffset = kDataOffset + kPointerSize;
static const int kFlagOffset = kNameOffset + kPointerSize;
static const int kExpectedReceiverTypeOffset = kFlagOffset + kPointerSize;
static const int kSize = kExpectedReceiverTypeOffset + kPointerSize;
private:
// Bit positions in flag.
static const int kAllCanReadBit = 0;
static const int kAllCanWriteBit = 1;
static const int kProhibitsOverwritingBit = 2;
class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
};
// Support for JavaScript accessors: A pair of a getter and a setter. Each
// accessor can either be
// * a pointer to a JavaScript function or proxy: a real accessor
// * undefined: considered an accessor by the spec, too, strangely enough
// * the hole: an accessor which has not been set
// * a pointer to a map: a transition used to ensure map sharing
class AccessorPair: public Struct {
public:
DECL_ACCESSORS(getter, Object)
DECL_ACCESSORS(setter, Object)
static inline AccessorPair* cast(Object* obj);
MUST_USE_RESULT MaybeObject* Copy();
Object* get(AccessorComponent component) {
return component == ACCESSOR_GETTER ? getter() : setter();
}
void set(AccessorComponent component, Object* value) {
if (component == ACCESSOR_GETTER) {
set_getter(value);
} else {
set_setter(value);
}
}
// Note: Returns undefined instead in case of a hole.
Object* GetComponent(AccessorComponent component);
// Set both components, skipping arguments which are a JavaScript null.
void SetComponents(Object* getter, Object* setter) {
if (!getter->IsNull()) set_getter(getter);
if (!setter->IsNull()) set_setter(setter);
}
bool ContainsAccessor() {
return IsJSAccessor(getter()) || IsJSAccessor(setter());
}
#ifdef OBJECT_PRINT
void AccessorPairPrint(FILE* out = stdout);
#endif
DECLARE_VERIFIER(AccessorPair)
static const int kGetterOffset = HeapObject::kHeaderSize;
static const int kSetterOffset = kGetterOffset + kPointerSize;
static const int kSize = kSetterOffset + kPointerSize;
private:
// Strangely enough, in addition to functions and harmony proxies, the spec
// requires us to consider undefined as a kind of accessor, too:
// var obj = {};
// Object.defineProperty(obj, "foo", {get: undefined});
// assertTrue("foo" in obj);
bool IsJSAccessor(Object* obj) {
return obj->IsSpecFunction() || obj->IsUndefined();
}
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorPair);
};
class AccessCheckInfo: public Struct {
public:
DECL_ACCESSORS(named_callback, Object)
DECL_ACCESSORS(indexed_callback, Object)
DECL_ACCESSORS(data, Object)
static inline AccessCheckInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void AccessCheckInfoPrint() {
AccessCheckInfoPrint(stdout);
}
void AccessCheckInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(AccessCheckInfo)
static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
static const int kSize = kDataOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
};
class InterceptorInfo: public Struct {
public:
DECL_ACCESSORS(getter, Object)
DECL_ACCESSORS(setter, Object)
DECL_ACCESSORS(query, Object)
DECL_ACCESSORS(deleter, Object)
DECL_ACCESSORS(enumerator, Object)
DECL_ACCESSORS(data, Object)
static inline InterceptorInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void InterceptorInfoPrint() {
InterceptorInfoPrint(stdout);
}
void InterceptorInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(InterceptorInfo)
static const int kGetterOffset = HeapObject::kHeaderSize;
static const int kSetterOffset = kGetterOffset + kPointerSize;
static const int kQueryOffset = kSetterOffset + kPointerSize;
static const int kDeleterOffset = kQueryOffset + kPointerSize;
static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
static const int kDataOffset = kEnumeratorOffset + kPointerSize;
static const int kSize = kDataOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
};
class CallHandlerInfo: public Struct {
public:
DECL_ACCESSORS(callback, Object)
DECL_ACCESSORS(data, Object)
static inline CallHandlerInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void CallHandlerInfoPrint() {
CallHandlerInfoPrint(stdout);
}
void CallHandlerInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(CallHandlerInfo)
static const int kCallbackOffset = HeapObject::kHeaderSize;
static const int kDataOffset = kCallbackOffset + kPointerSize;
static const int kSize = kDataOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
};
class TemplateInfo: public Struct {
public:
DECL_ACCESSORS(tag, Object)
DECL_ACCESSORS(property_list, Object)
DECLARE_VERIFIER(TemplateInfo)
static const int kTagOffset = HeapObject::kHeaderSize;
static const int kPropertyListOffset = kTagOffset + kPointerSize;
static const int kHeaderSize = kPropertyListOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
};
class FunctionTemplateInfo: public TemplateInfo {
public:
DECL_ACCESSORS(serial_number, Object)
DECL_ACCESSORS(call_code, Object)
DECL_ACCESSORS(property_accessors, Object)
DECL_ACCESSORS(prototype_template, Object)
DECL_ACCESSORS(parent_template, Object)
DECL_ACCESSORS(named_property_handler, Object)
DECL_ACCESSORS(indexed_property_handler, Object)
DECL_ACCESSORS(instance_template, Object)
DECL_ACCESSORS(class_name, Object)
DECL_ACCESSORS(signature, Object)
DECL_ACCESSORS(instance_call_handler, Object)
DECL_ACCESSORS(access_check_info, Object)
DECL_ACCESSORS(flag, Smi)
// Following properties use flag bits.
DECL_BOOLEAN_ACCESSORS(hidden_prototype)
DECL_BOOLEAN_ACCESSORS(undetectable)
// If the bit is set, object instances created by this function
// requires access check.
DECL_BOOLEAN_ACCESSORS(needs_access_check)
DECL_BOOLEAN_ACCESSORS(read_only_prototype)
static inline FunctionTemplateInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void FunctionTemplateInfoPrint() {
FunctionTemplateInfoPrint(stdout);
}
void FunctionTemplateInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(FunctionTemplateInfo)
static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
static const int kPrototypeTemplateOffset =
kPropertyAccessorsOffset + kPointerSize;
static const int kParentTemplateOffset =
kPrototypeTemplateOffset + kPointerSize;
static const int kNamedPropertyHandlerOffset =
kParentTemplateOffset + kPointerSize;
static const int kIndexedPropertyHandlerOffset =
kNamedPropertyHandlerOffset + kPointerSize;
static const int kInstanceTemplateOffset =
kIndexedPropertyHandlerOffset + kPointerSize;
static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
static const int kSignatureOffset = kClassNameOffset + kPointerSize;
static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
static const int kAccessCheckInfoOffset =
kInstanceCallHandlerOffset + kPointerSize;
static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
static const int kSize = kFlagOffset + kPointerSize;
private:
// Bit position in the flag, from least significant bit position.
static const int kHiddenPrototypeBit = 0;
static const int kUndetectableBit = 1;
static const int kNeedsAccessCheckBit = 2;
static const int kReadOnlyPrototypeBit = 3;
DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
};
class ObjectTemplateInfo: public TemplateInfo {
public:
DECL_ACCESSORS(constructor, Object)
DECL_ACCESSORS(internal_field_count, Object)
static inline ObjectTemplateInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ObjectTemplateInfoPrint() {
ObjectTemplateInfoPrint(stdout);
}
void ObjectTemplateInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(ObjectTemplateInfo)
static const int kConstructorOffset = TemplateInfo::kHeaderSize;
static const int kInternalFieldCountOffset =
kConstructorOffset + kPointerSize;
static const int kSize = kInternalFieldCountOffset + kPointerSize;
};
class SignatureInfo: public Struct {
public:
DECL_ACCESSORS(receiver, Object)
DECL_ACCESSORS(args, Object)
static inline SignatureInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void SignatureInfoPrint() {
SignatureInfoPrint(stdout);
}
void SignatureInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(SignatureInfo)
static const int kReceiverOffset = Struct::kHeaderSize;
static const int kArgsOffset = kReceiverOffset + kPointerSize;
static const int kSize = kArgsOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
};
class TypeSwitchInfo: public Struct {
public:
DECL_ACCESSORS(types, Object)
static inline TypeSwitchInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void TypeSwitchInfoPrint() {
TypeSwitchInfoPrint(stdout);
}
void TypeSwitchInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(TypeSwitchInfo)
static const int kTypesOffset = Struct::kHeaderSize;
static const int kSize = kTypesOffset + kPointerSize;
};
#ifdef ENABLE_DEBUGGER_SUPPORT
// The DebugInfo class holds additional information for a function being
// debugged.
class DebugInfo: public Struct {
public:
// The shared function info for the source being debugged.
DECL_ACCESSORS(shared, SharedFunctionInfo)
// Code object for the original code.
DECL_ACCESSORS(original_code, Code)
// Code object for the patched code. This code object is the code object
// currently active for the function.
DECL_ACCESSORS(code, Code)
// Fixed array holding status information for each active break point.
DECL_ACCESSORS(break_points, FixedArray)
// Check if there is a break point at a code position.
bool HasBreakPoint(int code_position);
// Get the break point info object for a code position.
Object* GetBreakPointInfo(int code_position);
// Clear a break point.
static void ClearBreakPoint(Handle<DebugInfo> debug_info,
int code_position,
Handle<Object> break_point_object);
// Set a break point.
static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
int source_position, int statement_position,
Handle<Object> break_point_object);
// Get the break point objects for a code position.
Object* GetBreakPointObjects(int code_position);
// Find the break point info holding this break point object.
static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
Handle<Object> break_point_object);
// Get the number of break points for this function.
int GetBreakPointCount();
static inline DebugInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void DebugInfoPrint() {
DebugInfoPrint(stdout);
}
void DebugInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(DebugInfo)
static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
static const int kActiveBreakPointsCountIndex =
kPatchedCodeIndex + kPointerSize;
static const int kBreakPointsStateIndex =
kActiveBreakPointsCountIndex + kPointerSize;
static const int kSize = kBreakPointsStateIndex + kPointerSize;
private:
static const int kNoBreakPointInfo = -1;
// Lookup the index in the break_points array for a code position.
int GetBreakPointInfoIndex(int code_position);
DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
};
// The BreakPointInfo class holds information for break points set in a
// function. The DebugInfo object holds a BreakPointInfo object for each code
// position with one or more break points.
class BreakPointInfo: public Struct {
public:
// The position in the code for the break point.
DECL_ACCESSORS(code_position, Smi)
// The position in the source for the break position.
DECL_ACCESSORS(source_position, Smi)
// The position in the source for the last statement before this break
// position.
DECL_ACCESSORS(statement_position, Smi)
// List of related JavaScript break points.
DECL_ACCESSORS(break_point_objects, Object)
// Removes a break point.
static void ClearBreakPoint(Handle<BreakPointInfo> info,
Handle<Object> break_point_object);
// Set a break point.
static void SetBreakPoint(Handle<BreakPointInfo> info,
Handle<Object> break_point_object);
// Check if break point info has this break point object.
static bool HasBreakPointObject(Handle<BreakPointInfo> info,
Handle<Object> break_point_object);
// Get the number of break points for this code position.
int GetBreakPointCount();
static inline BreakPointInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void BreakPointInfoPrint() {
BreakPointInfoPrint(stdout);
}
void BreakPointInfoPrint(FILE* out);
#endif
DECLARE_VERIFIER(BreakPointInfo)
static const int kCodePositionIndex = Struct::kHeaderSize;
static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
static const int kStatementPositionIndex =
kSourcePositionIndex + kPointerSize;
static const int kBreakPointObjectsIndex =
kStatementPositionIndex + kPointerSize;
static const int kSize = kBreakPointObjectsIndex + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
};
#endif // ENABLE_DEBUGGER_SUPPORT
#undef DECL_BOOLEAN_ACCESSORS
#undef DECL_ACCESSORS
#undef DECLARE_VERIFIER
#define VISITOR_SYNCHRONIZATION_TAGS_LIST(V) \
V(kSymbolTable, "symbol_table", "(Symbols)") \
V(kExternalStringsTable, "external_strings_table", "(External strings)") \
V(kStrongRootList, "strong_root_list", "(Strong roots)") \
V(kSymbol, "symbol", "(Symbol)") \
V(kBootstrapper, "bootstrapper", "(Bootstrapper)") \
V(kTop, "top", "(Isolate)") \
V(kRelocatable, "relocatable", "(Relocatable)") \
V(kDebug, "debug", "(Debugger)") \
V(kCompilationCache, "compilationcache", "(Compilation cache)") \
V(kHandleScope, "handlescope", "(Handle scope)") \
V(kBuiltins, "builtins", "(Builtins)") \
V(kGlobalHandles, "globalhandles", "(Global handles)") \
V(kThreadManager, "threadmanager", "(Thread manager)") \
V(kExtensions, "Extensions", "(Extensions)")
class VisitorSynchronization : public AllStatic {
public:
#define DECLARE_ENUM(enum_item, ignore1, ignore2) enum_item,
enum SyncTag {
VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_ENUM)
kNumberOfSyncTags
};
#undef DECLARE_ENUM
static const char* const kTags[kNumberOfSyncTags];
static const char* const kTagNames[kNumberOfSyncTags];
};
// Abstract base class for visiting, and optionally modifying, the
// pointers contained in Objects. Used in GC and serialization/deserialization.
class ObjectVisitor BASE_EMBEDDED {
public:
virtual ~ObjectVisitor() {}
// Visits a contiguous arrays of pointers in the half-open range
// [start, end). Any or all of the values may be modified on return.
virtual void VisitPointers(Object** start, Object** end) = 0;
// To allow lazy clearing of inline caches the visitor has
// a rich interface for iterating over Code objects..
// Visits a code target in the instruction stream.
virtual void VisitCodeTarget(RelocInfo* rinfo);
// Visits a code entry in a JS function.
virtual void VisitCodeEntry(Address entry_address);
// Visits a global property cell reference in the instruction stream.
virtual void VisitGlobalPropertyCell(RelocInfo* rinfo);
// Visits a runtime entry in the instruction stream.
virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
// Visits the resource of an ASCII or two-byte string.
virtual void VisitExternalAsciiString(
v8::String::ExternalAsciiStringResource** resource) {}
virtual void VisitExternalTwoByteString(
v8::String::ExternalStringResource** resource) {}
// Visits a debug call target in the instruction stream.
virtual void VisitDebugTarget(RelocInfo* rinfo);
// Handy shorthand for visiting a single pointer.
virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
// Visit pointer embedded into a code object.
virtual void VisitEmbeddedPointer(RelocInfo* rinfo);
// Visits a contiguous arrays of external references (references to the C++
// heap) in the half-open range [start, end). Any or all of the values
// may be modified on return.
virtual void VisitExternalReferences(Address* start, Address* end) {}
virtual void VisitExternalReference(RelocInfo* rinfo);
inline void VisitExternalReference(Address* p) {
VisitExternalReferences(p, p + 1);
}
// Visits a handle that has an embedder-assigned class ID.
virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
// Intended for serialization/deserialization checking: insert, or
// check for the presence of, a tag at this position in the stream.
// Also used for marking up GC roots in heap snapshots.
virtual void Synchronize(VisitorSynchronization::SyncTag tag) {}
};
class StructBodyDescriptor : public
FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
public:
static inline int SizeOf(Map* map, HeapObject* object) {
return map->instance_size();
}
};
// BooleanBit is a helper class for setting and getting a bit in an
// integer or Smi.
class BooleanBit : public AllStatic {
public:
static inline bool get(Smi* smi, int bit_position) {
return get(smi->value(), bit_position);
}
static inline bool get(int value, int bit_position) {
return (value & (1 << bit_position)) != 0;
}
static inline Smi* set(Smi* smi, int bit_position, bool v) {
return Smi::FromInt(set(smi->value(), bit_position, v));
}
static inline int set(int value, int bit_position, bool v) {
if (v) {
value |= (1 << bit_position);
} else {
value &= ~(1 << bit_position);
}
return value;
}
};
} } // namespace v8::internal
#endif // V8_OBJECTS_H_
|