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
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=2 et tw=0 ft=c:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef vm_Opcodes_h
#define vm_Opcodes_h
#include <stddef.h>
#include <stdint.h>
// clang-format off
/*
* [SMDOC] Bytecode Definitions
*
* SpiderMonkey bytecode instructions.
*
* To use this header, define a macro of the form:
*
* #define MACRO(op, op_snake, token, length, nuses, ndefs, format) ...
*
* Then `FOR_EACH_OPCODE(MACRO)` invokes `MACRO` for every opcode.
*
* Field Description
* ----- -----------
* op UpperCamelCase form of opcode id
* op_snake snake_case form of opcode id
* token Pretty-printer string, or null if ugly
* length Number of bytes including any immediate operands
* nuses Number of stack slots consumed by bytecode, -1 if variadic
* ndefs Number of stack slots produced by bytecode
* format JOF_ flags describing instruction operand layout, etc.
*
* For more about `format`, see the comments on the `JOF_` constants defined in
* BytecodeUtil.h.
*
*
* [SMDOC] Bytecode Invariants
*
* Creating scripts that do not follow the rules can lead to undefined
* behavior. Bytecode has many consumers, not just the interpreter: JITs,
* analyses, the debugger. That's why the rules below apply even to code that
* can't be reached in ordinary execution (such as code after an infinite loop
* or inside an `if (false)` block).
*
* The `code()` of a script must be a packed (not aligned) sequence of valid
* instructions from start to end. Each instruction has a single byte opcode
* followed by a number of operand bytes based on the opcode.
*
* ## Jump instructions
*
* Operands named `offset`, `forwardOffset`, or `defaultOffset` are jump
* offsets, the distance in bytes from the start of the current instruction to
* the start of another instruction in the same script. Operands named
* `forwardOffset` or `defaultOffset` must be positive.
*
* Forward jumps must jump to a `JSOp::JumpTarget` instruction. Backward jumps,
* indicated by negative offsets, must jump to a `JSOp::LoopHead` instruction.
* Jump offsets can't be zero.
*
* Needless to say, scripts must not contain overlapping instruction sequences
* (in the sense of <https://en.wikipedia.org/wiki/Overlapping_gene>).
*
* A script's `trynotes` and `scopeNotes` impose further constraints. Each try
* note and each scope note marks a region of the bytecode where some invariant
* holds, or some cleanup behavior is needed--that there's a for-in iterator in
* a particular stack slot, for instance, which must be closed on error. All
* paths into the span must establish that invariant. In practice, this means
* other code never jumps into the span: the only way in is to execute the
* bytecode instruction that sets up the invariant (in our example,
* `JSOp::Iter`).
*
* If a script's `trynotes` (see "Try Notes" in JSScript.h) contain a
* `JSTRY_CATCH` or `JSTRY_FINALLY` span, there must be a `JSOp::Try`
* instruction immediately before the span and a `JSOp::JumpTarget immediately
* after it. Instructions must not jump to this `JSOp::JumpTarget`. (The VM puts
* us there on exception.) Furthermore, the instruction sequence immediately
* following a `JSTRY_CATCH` span must read `JumpTarget; Exception` or, in
* non-function scripts, `JumpTarget; Undefined; SetRval; Exception`. (These
* instructions run with an exception pending; other instructions aren't
* designed to handle that.)
*
* Unreachable instructions are allowed, but they have to follow all the rules.
*
* Control must not reach the end of a script. (Currently, the last instruction
* is always JSOp::RetRval.)
*
* ## Other operands
*
* Operands named `nameIndex` or `atomIndex` (which appear on instructions that
* have `JOF_ATOM` in the `format` field) must be valid indexes into
* `script->atoms()`.
*
* Operands named `argc` (`JOF_ARGC`) are argument counts for call
* instructions. `argc` must be small enough that the instruction's nuses is <=
* the current stack depth (see "Stack depth" below).
*
* Operands named `argno` (`JOF_QARG`) refer to an argument of the current
* function. `argno` must be in the range `0..script->function()->nargs()`.
* Instructions with these operands must appear only in function scripts.
*
* Operands named `localno` (`JOF_LOCAL`) refer to a local variable stored in
* the stack frame. `localno` must be in the range `0..script->nfixed()`.
*
* Operands named `resumeIndex` (`JOF_RESUMEINDEX`) refer to a resume point in
* the current script. `resumeIndex` must be a valid index into
* `script->resumeOffsets()`.
*
* Operands named `hops` and `slot` (`JOF_ENVCOORD`) refer a slot in an
* `EnvironmentObject`. At run time, they must point to a fixed slot in an
* object on the current environment chain. See `EnvironmentCoordinates`.
*
* Operands with the following names must be valid indexes into
* `script->gcthings()`, and the pointer in the vector must point to the right
* type of thing:
*
* - `objectIndex` (`JOF_OBJECT`): `PlainObject*` or `ArrayObject*`
* - `baseobjIndex` (`JOF_OBJECT`): `PlainObject*`
* - `funcIndex` (`JOF_OBJECT`): `JSFunction*`
* - `regexpIndex` (`JOF_REGEXP`): `RegExpObject*`
* - `shapeIndex` (`JOF_SHAPE`): `Shape*`
* - `scopeIndex` (`JOF_SCOPE`): `Scope*`
* - `lexicalScopeIndex` (`JOF_SCOPE`): `LexicalScope*`
* - `classBodyScopeIndex` (`JOF_SCOPE`): `ClassBodyScope*`
* - `withScopeIndex` (`JOF_SCOPE`): `WithScope*`
* - `bigIntIndex` (`JOF_BIGINT`): `BigInt*`
*
* Operands named `icIndex` (`JOF_ICINDEX`) must be exactly the number of
* preceding instructions in the script that have the JOF_IC flag.
* (Rationale: Each JOF_IC instruction has a unique entry in
* `script->jitScript()->icEntries()`. At run time, in the bytecode
* interpreter, we have to find that entry. We could store the IC index as an
* operand to each JOF_IC instruction, but it's more memory-efficient to use a
* counter and reset the counter to `icIndex` after each jump.)
*
* ## Stack depth
*
* Each instruction has a compile-time stack depth, the number of values on the
* interpreter stack just before executing the instruction. It isn't explicitly
* present in the bytecode itself, but (for reachable instructions, anyway)
* it's a function of the bytecode.
*
* - The first instruction has stack depth 0.
*
* - Each successor of an instruction X has a stack depth equal to
*
* X's stack depth - `js::StackUses(X)` + `js::StackDefs(X)`
*
* except for `JSOp::Case` (below).
*
* X's "successors" are: the next instruction in the script, if
* `js::FlowsIntoNext(op)` is true for X's opcode; one or more
* `JSOp::JumpTarget`s elsewhere, if X is a forward jump or
* `JSOp::TableSwitch`; and/or a `JSOp::LoopHead` if it's a backward jump.
*
* - `JSOp::Case` is a special case because its stack behavior is eccentric.
* The formula above is correct for the next instruction. The jump target
* has a stack depth that is 1 less.
*
* - The `JSOp::JumpTarget` instruction immediately following a `JSTRY_CATCH`
* or `JSTRY_FINALLY` span has the same stack depth as the `JSOp::Try`
* instruction that precedes the span.
*
* Every instruction covered by the `JSTRY_CATCH` or `JSTRY_FINALLY` span
* must have a stack depth >= that value, so that error recovery is
* guaranteed to find enough values on the stack to resume there.
*
* - `script->nslots() - script->nfixed()` must be >= the maximum stack
* depth of any instruction in `script`. (The stack frame must be big
* enough to run the code.)
*
* `BytecodeParser::parse()` computes stack depths for every reachable
* instruction in a script.
*
* ## Scopes and environments
*
* As with stack depth, each instruction has a static scope, which is a
* compile-time characterization of the eventual run-time environment chain
* when that instruction executes. Just as every instruction has a stack budget
* (nuses/ndefs), every instruction either pushes a scope, pops a scope, or
* neither. The same successor relation applies as above.
*
* Every scope used in a script is stored in the `JSScript::gcthings()` vector.
* They can be accessed using `getScope(index)` if you know what `index` to
* pass.
*
* The scope of every instruction (that's reachable via the successor relation)
* is given in two independent ways: by the bytecode itself and by the scope
* notes. The two sources must agree.
*
* ## Further rules
*
* All reachable instructions must be reachable without taking any backward
* edges.
*
* Instructions with the `JOF_CHECKSLOPPY` flag must not be used in strict mode
* code. `JOF_CHECKSTRICT` instructions must not be used in nonstrict code.
*
* Many instructions have their own additional rules. These are documented on
* the various opcodes below (look for the word "must").
*/
// clang-format on
// clang-format off
/*
* SpiderMonkey bytecode categorization (as used in generated documentation):
*
* [Index]
* [Constants]
* [Compound primitives]
* Record literals
* Tuple literals
* [Expressions]
* Unary operators
* Binary operators
* Conversions
* Other expressions
* [Objects]
* Creating objects
* Defining properties
* Accessing properties
* Super
* Enumeration
* Iteration
* SetPrototype
* Array literals
* RegExp literals
* Built-in objects
* [Functions]
* Creating functions
* Creating constructors
* Calls
* Generators and async functions
* [Control flow]
* Jump targets
* Jumps
* Return
* Exceptions
* [Variables and scopes]
* Initialization
* Looking up bindings
* Getting binding values
* Setting binding values
* Entering and leaving environments
* Creating and deleting bindings
* Function environment setup
* [Stack operations]
* [Other]
*/
// clang-format on
// clang-format off
#define FOR_EACH_OPCODE(MACRO) \
/*
* Push `undefined`.
*
* Category: Constants
* Operands:
* Stack: => undefined
*/ \
MACRO(Undefined, undefined, "", 1, 0, 1, JOF_BYTE) \
/*
* Push `null`.
*
* Category: Constants
* Operands:
* Stack: => null
*/ \
MACRO(Null, null, "null", 1, 0, 1, JOF_BYTE) \
/*
* Push a boolean constant.
*
* Category: Constants
* Operands:
* Stack: => true/false
*/ \
MACRO(False, false_, "false", 1, 0, 1, JOF_BYTE) \
MACRO(True, true_, "true", 1, 0, 1, JOF_BYTE) \
/*
* Push the `int32_t` immediate operand as an `Int32Value`.
*
* `JSOp::Zero`, `JSOp::One`, `JSOp::Int8`, `JSOp::Uint16`, and `JSOp::Uint24`
* are all compact encodings for `JSOp::Int32`.
*
* Category: Constants
* Operands: int32_t val
* Stack: => val
*/ \
MACRO(Int32, int32, NULL, 5, 0, 1, JOF_INT32) \
/*
* Push the number `0`.
*
* Category: Constants
* Operands:
* Stack: => 0
*/ \
MACRO(Zero, zero, "0", 1, 0, 1, JOF_BYTE) \
/*
* Push the number `1`.
*
* Category: Constants
* Operands:
* Stack: => 1
*/ \
MACRO(One, one, "1", 1, 0, 1, JOF_BYTE) \
/*
* Push the `int8_t` immediate operand as an `Int32Value`.
*
* Category: Constants
* Operands: int8_t val
* Stack: => val
*/ \
MACRO(Int8, int8, NULL, 2, 0, 1, JOF_INT8) \
/*
* Push the `uint16_t` immediate operand as an `Int32Value`.
*
* Category: Constants
* Operands: uint16_t val
* Stack: => val
*/ \
MACRO(Uint16, uint16, NULL, 3, 0, 1, JOF_UINT16) \
/*
* Push the `uint24_t` immediate operand as an `Int32Value`.
*
* Category: Constants
* Operands: uint24_t val
* Stack: => val
*/ \
MACRO(Uint24, uint24, NULL, 4, 0, 1, JOF_UINT24) \
/*
* Push the 64-bit floating-point immediate operand as a `DoubleValue`.
*
* If the operand is a NaN, it must be the canonical NaN (see
* `JS::detail::CanonicalizeNaN`).
*
* Category: Constants
* Operands: double val
* Stack: => val
*/ \
MACRO(Double, double_, NULL, 9, 0, 1, JOF_DOUBLE) \
/*
* Push the BigInt constant `script->getBigInt(bigIntIndex)`.
*
* Category: Constants
* Operands: uint32_t bigIntIndex
* Stack: => bigint
*/ \
MACRO(BigInt, big_int, NULL, 5, 0, 1, JOF_BIGINT) \
/*
* Push the string constant `script->getAtom(atomIndex)`.
*
* Category: Constants
* Operands: uint32_t atomIndex
* Stack: => string
*/ \
MACRO(String, string, NULL, 5, 0, 1, JOF_STRING) \
/*
* Push a well-known symbol.
*
* `symbol` must be in range for `JS::SymbolCode`.
*
* Category: Constants
* Operands: uint8_t symbol (the JS::SymbolCode of the symbol to use)
* Stack: => symbol
*/ \
MACRO(Symbol, symbol, NULL, 2, 0, 1, JOF_UINT8) \
/*
* Pop the top value on the stack, discard it, and push `undefined`.
*
* Implements: [The `void` operator][1], step 3.
*
* [1]: https://tc39.es/ecma262/#sec-void-operator
*
* Category: Expressions
* Type: Unary operators
* Operands:
* Stack: val => undefined
*/ \
MACRO(Void, void_, NULL, 1, 1, 1, JOF_BYTE) \
/*
* [The `typeof` operator][1].
*
* Infallible. The result is always a string that depends on the [type][2]
* of `val`.
*
* `JSOp::Typeof` and `JSOp::TypeofExpr` are the same except
* that--amazingly--`JSOp::Typeof` affects the behavior of an immediately
* *preceding* `JSOp::GetName` or `JSOp::GetGName` instruction! This is how
* we implement [`typeof`][1] step 2, making `typeof nonExistingVariable`
* return `"undefined"` instead of throwing a ReferenceError.
*
* In a global scope:
*
* - `typeof x` compiles to `GetGName "x"; Typeof`.
* - `typeof (0, x)` compiles to `GetGName "x"; TypeofExpr`.
*
* Emitting the same bytecode for these two expressions would be a bug.
* Per spec, the latter throws a ReferenceError if `x` doesn't exist.
*
* [1]: https://tc39.es/ecma262/#sec-typeof-operator
* [2]: https://tc39.es/ecma262/#sec-ecmascript-language-types
*
* Category: Expressions
* Type: Unary operators
* Operands:
* Stack: val => (typeof val)
*/ \
MACRO(Typeof, typeof_, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
MACRO(TypeofExpr, typeof_expr, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* [The unary `+` operator][1].
*
* `+val` doesn't do any actual math. It just calls [ToNumber][2](val).
*
* The conversion can call `.toString()`/`.valueOf()` methods and can
* throw. The result on success is always a Number. (Per spec, unary `-`
* supports BigInts, but unary `+` does not.)
*
* [1]: https://tc39.es/ecma262/#sec-unary-plus-operator
* [2]: https://tc39.es/ecma262/#sec-tonumber
*
* Category: Expressions
* Type: Unary operators
* Operands:
* Stack: val => (+val)
*/ \
MACRO(Pos, pos, "+ ", 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* [The unary `-` operator][1].
*
* Convert `val` to a numeric value, then push `-val`. The conversion can
* call `.toString()`/`.valueOf()` methods and can throw. The result on
* success is always numeric.
*
* [1]: https://tc39.es/ecma262/#sec-unary-minus-operator
*
* Category: Expressions
* Type: Unary operators
* Operands:
* Stack: val => (-val)
*/ \
MACRO(Neg, neg, "- ", 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* [The bitwise NOT operator][1] (`~`).
*
* `val` is converted to an integer, then bitwise negated. The conversion
* can call `.toString()`/`.valueOf()` methods and can throw. The result on
* success is always an Int32 or BigInt value.
*
* [1]: https://tc39.es/ecma262/#sec-bitwise-not-operator
*
* Category: Expressions
* Type: Unary operators
* Operands:
* Stack: val => (~val)
*/ \
MACRO(BitNot, bit_not, "~", 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* [The logical NOT operator][1] (`!`).
*
* `val` is first converted with [ToBoolean][2], then logically
* negated. The result is always a boolean value. This does not call
* user-defined methods and can't throw.
*
* [1]: https://tc39.es/ecma262/#sec-logical-not-operator
* [2]: https://tc39.es/ecma262/#sec-toboolean
*
* Category: Expressions
* Type: Unary operators
* Operands:
* Stack: val => (!val)
*/ \
MACRO(Not, not_, "!", 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* [Binary bitwise operations][1] (`|`, `^`, `&`).
*
* The arguments are converted to integers first. The conversion can call
* `.toString()`/`.valueOf()` methods and can throw. The result on success
* is always an Int32 or BigInt Value.
*
* [1]: https://tc39.es/ecma262/#sec-binary-bitwise-operators
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval OP rval)
*/ \
MACRO(BitOr, bit_or, "|", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(BitXor, bit_xor, "^", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(BitAnd, bit_and, "&", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* Loose equality operators (`==` and `!=`).
*
* Pop two values, compare them, and push the boolean result. The
* comparison may perform conversions that call `.toString()`/`.valueOf()`
* methods and can throw.
*
* Implements: [Abstract Equality Comparison][1].
*
* [1]: https://tc39.es/ecma262/#sec-abstract-equality-comparison
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval OP rval)
*/ \
MACRO(Eq, eq, "==", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(Ne, ne, "!=", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* Strict equality operators (`===` and `!==`).
*
* Pop two values, check whether they're equal, and push the boolean
* result. This does not call user-defined methods and can't throw
* (except possibly due to OOM while flattening a string).
*
* Implements: [Strict Equality Comparison][1].
*
* [1]: https://tc39.es/ecma262/#sec-strict-equality-comparison
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval OP rval)
*/ \
MACRO(StrictEq, strict_eq, "===", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(StrictNe, strict_ne, "!==", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* Relative operators (`<`, `>`, `<=`, `>=`).
*
* Pop two values, compare them, and push the boolean result. The
* comparison may perform conversions that call `.toString()`/`.valueOf()`
* methods and can throw.
*
* Implements: [Relational Operators: Evaluation][1].
*
* [1]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval OP rval)
*/ \
MACRO(Lt, lt, "<", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(Gt, gt, ">", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(Le, le, "<=", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(Ge, ge, ">=", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* [The `instanceof` operator][1].
*
* This throws a `TypeError` if `target` is not an object. It calls
* `target[Symbol.hasInstance](value)` if the method exists. On success,
* the result is always a boolean value.
*
* [1]: https://tc39.es/ecma262/#sec-instanceofoperator
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: value, target => (value instanceof target)
*/ \
MACRO(Instanceof, instanceof, "instanceof", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* [The `in` operator][1].
*
* Push `true` if `obj` has a property with the key `id`. Otherwise push `false`.
*
* This throws a `TypeError` if `obj` is not an object. This can fire
* proxy hooks and can throw. On success, the result is always a boolean
* value.
*
* [1]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: id, obj => (id in obj)
*/ \
MACRO(In, in_, "in", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* [Bitwise shift operators][1] (`<<`, `>>`, `>>>`).
*
* Pop two values, convert them to integers, perform a bitwise shift, and
* push the result.
*
* Conversion can call `.toString()`/`.valueOf()` methods and can throw.
* The result on success is always an Int32 or BigInt Value.
*
* [1]: https://tc39.es/ecma262/#sec-bitwise-shift-operators
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval OP rval)
*/ \
MACRO(Lsh, lsh, "<<", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(Rsh, rsh, ">>", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(Ursh, ursh, ">>>", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* [The binary `+` operator][1].
*
* Pop two values, convert them to primitive values, add them, and push the
* result. If both values are numeric, add them; if either is a
* string, do string concatenation instead.
*
* The conversion can call `.toString()`/`.valueOf()` methods and can throw.
*
* [1]: https://tc39.es/ecma262/#sec-addition-operator-plus-runtime-semantics-evaluation
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval + rval)
*/ \
MACRO(Add, add, "+", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* [The binary `-` operator][1].
*
* Pop two values, convert them to numeric values, subtract the top value
* from the other one, and push the result.
*
* The conversion can call `.toString()`/`.valueOf()` methods and can
* throw. On success, the result is always numeric.
*
* [1]: https://tc39.es/ecma262/#sec-subtraction-operator-minus-runtime-semantics-evaluation
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval - rval)
*/ \
MACRO(Sub, sub, "-", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* Add or subtract 1.
*
* `val` must already be a numeric value, such as the result of
* `JSOp::ToNumeric`.
*
* Implements: [The `++` and `--` operators][1], step 3 of each algorithm.
*
* [1]: https://tc39.es/ecma262/#sec-postfix-increment-operator
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: val => (val +/- 1)
*/ \
MACRO(Inc, inc, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
MACRO(Dec, dec, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* [The multiplicative operators][1] (`*`, `/`, `%`).
*
* Pop two values, convert them to numeric values, do math, and push the
* result.
*
* The conversion can call `.toString()`/`.valueOf()` methods and can
* throw. On success, the result is always numeric.
*
* [1]: https://tc39.es/ecma262/#sec-multiplicative-operators-runtime-semantics-evaluation
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval OP rval)
*/ \
MACRO(Mul, mul, "*", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(Div, div, "/", 1, 2, 1, JOF_BYTE|JOF_IC) \
MACRO(Mod, mod, "%", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* [The exponentiation operator][1] (`**`).
*
* Pop two values, convert them to numeric values, do exponentiation, and
* push the result. The top value is the exponent.
*
* The conversion can call `.toString()`/`.valueOf()` methods and can
* throw. This throws a RangeError if both values are BigInts and the
* exponent is negative.
*
* [1]: https://tc39.es/ecma262/#sec-exp-operator
*
* Category: Expressions
* Type: Binary operators
* Operands:
* Stack: lval, rval => (lval ** rval)
*/ \
MACRO(Pow, pow, "**", 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* Convert a value to a property key.
*
* Implements: [ToPropertyKey][1], except that if the result would be the
* string representation of some integer in the range 0..2^31, we push the
* corresponding Int32 value instead. This is because the spec insists that
* array indices are strings, whereas for us they are integers.
*
* This is used for code like `++obj[index]`, which must do both a
* `JSOp::GetElem` and a `JSOp::SetElem` with the same property key. Both
* instructions would convert `index` to a property key for us, but the
* spec says to convert it only once.
*
* The conversion can call `.toString()`/`.valueOf()` methods and can
* throw.
*
* [1]: https://tc39.es/ecma262/#sec-topropertykey
*
* Category: Expressions
* Type: Conversions
* Operands:
* Stack: propertyNameValue => propertyKey
*/ \
MACRO(ToPropertyKey, to_property_key, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* Convert a value to a numeric value (a Number or BigInt).
*
* Implements: [ToNumeric][1](val).
*
* Note: This is used to implement [`++` and `--`][2]. Surprisingly, it's
* not possible to get the right behavior using `JSOp::Add` and `JSOp::Sub`
* alone. For one thing, `JSOp::Add` sometimes does string concatenation,
* while `++` always does numeric addition. More fundamentally, the result
* of evaluating `x--` is ToNumeric(old value of `x`), a value that the
* sequence `GetLocal "x"; One; Sub; SetLocal "x"` does not give us.
*
* [1]: https://tc39.es/ecma262/#sec-tonumeric
* [2]: https://tc39.es/ecma262/#sec-postfix-increment-operator
*
* Category: Expressions
* Type: Conversions
* Operands:
* Stack: val => ToNumeric(val)
*/ \
MACRO(ToNumeric, to_numeric, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* Convert a value to a string.
*
* Implements: [ToString][1](val).
*
* Note: This is used in code for template literals, like `${x}${y}`. Each
* substituted value must be converted using ToString. `JSOp::Add` by itself
* would do a slightly wrong kind of conversion (hint="number" rather than
* hint="string").
*
* [1]: https://tc39.es/ecma262/#sec-tostring
*
* Category: Expressions
* Type: Conversions
* Stack: val => ToString(val)
*/ \
MACRO(ToString, to_string, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Test whether the value on top of the stack is `NullValue` or
* `UndefinedValue` and push the boolean result.
*
* Category: Expressions
* Type: Other expressions
* Operands:
* Stack: val => val, IsNullOrUndefined(val)
*/ \
MACRO(IsNullOrUndefined, is_null_or_undefined, NULL, 1, 1, 2, JOF_BYTE) \
/*
* Push the global `this` value. Not to be confused with the `globalThis`
* property on the global.
*
* This must be used only in scopes where `this` refers to the global
* `this`.
*
* Category: Expressions
* Type: Other expressions
* Operands:
* Stack: => this
*/ \
MACRO(GlobalThis, global_this, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Push the global `this` value for non-syntactic scope. Not to be confused
* with the `globalThis` property on the global.
*
* This must be used only in scopes where `this` refers to the global
* `this`.
*
* Category: Expressions
* Type: Other expressions
* Operands:
* Stack: => this
*/ \
MACRO(NonSyntacticGlobalThis, non_syntactic_global_this, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Push the value of `new.target`.
*
* The result is a constructor or `undefined`.
*
* This must be used only in non-arrow function scripts.
*
* Implements: [GetNewTarget][1].
*
* [1]: https://tc39.es/ecma262/#sec-getnewtarget
*
* Category: Expressions
* Type: Other expressions
* Operands:
* Stack: => new.target
*/ \
MACRO(NewTarget, new_target, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Dynamic import of the module specified by the string value on the top of
* the stack.
*
* Implements: [Import Calls][1].
*
* [1]: https://tc39.es/ecma262/#sec-import-calls
*
* Category: Expressions
* Type: Other expressions
* Operands:
* Stack: moduleId, options => promise
*/ \
MACRO(DynamicImport, dynamic_import, NULL, 1, 2, 1, JOF_BYTE) \
/*
* Push the `import.meta` object.
*
* This must be used only in module code.
*
* Category: Expressions
* Type: Other expressions
* Operands:
* Stack: => import.meta
*/ \
MACRO(ImportMeta, import_meta, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Create and push a new object with no properties.
*
* Category: Objects
* Type: Creating objects
* Operands:
* Stack: => obj
*/ \
MACRO(NewInit, new_init, NULL, 1, 0, 1, JOF_BYTE|JOF_IC) \
/*
* Create and push a new object of a predetermined shape.
*
* The new object has the shape `script->getShape(shapeIndex)`.
* Subsequent `InitProp` instructions must fill in all slots of the new
* object before it is used in any other way.
*
* Category: Objects
* Type: Creating objects
* Operands: uint32_t shapeIndex
* Stack: => obj
*/ \
MACRO(NewObject, new_object, NULL, 5, 0, 1, JOF_SHAPE|JOF_IC) \
/*
* Push a preconstructed object.
*
* Going one step further than `JSOp::NewObject`, this instruction doesn't
* just reuse the shape--it actually pushes the preconstructed object
* `script->getObject(objectIndex)` right onto the stack. The object must
* be a singleton `PlainObject` or `ArrayObject`.
*
* The spec requires that an *ObjectLiteral* or *ArrayLiteral* creates a
* new object every time it's evaluated, so this instruction must not be
* used anywhere it might be executed more than once.
*
* This may only be used in non-function run-once scripts. Care also must
* be taken to not emit in loops or other constructs where it could run
* more than once.
*
* Category: Objects
* Type: Creating objects
* Operands: uint32_t objectIndex
* Stack: => obj
*/ \
MACRO(Object, object, NULL, 5, 0, 1, JOF_OBJECT) \
/*
* Create and push a new ordinary object with the provided [[Prototype]].
*
* This is used to create the `.prototype` object for derived classes.
*
* Category: Objects
* Type: Creating objects
* Operands:
* Stack: proto => obj
*/ \
MACRO(ObjWithProto, obj_with_proto, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Define a data property on an object.
*
* `obj` must be an object.
*
* Implements: [CreateDataPropertyOrThrow][1] as used in
* [PropertyDefinitionEvaluation][2] of regular and shorthand
* *PropertyDefinition*s.
*
* [1]: https://tc39.es/ecma262/#sec-createdatapropertyorthrow
* [2]: https://tc39.es/ecma262/#sec-object-initializer-runtime-semantics-propertydefinitionevaluation
*
* Category: Objects
* Type: Defining properties
* Operands: uint32_t nameIndex
* Stack: obj, val => obj
*/ \
MACRO(InitProp, init_prop, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPINIT|JOF_IC) \
/*
* Like `JSOp::InitProp`, but define a non-enumerable property.
*
* This is used to define class methods.
*
* Implements: [PropertyDefinitionEvaluation][1] for methods, steps 3 and
* 4, when *enumerable* is false.
*
* [1]: https://tc39.es/ecma262/#sec-method-definitions-runtime-semantics-propertydefinitionevaluation
*
* Category: Objects
* Type: Defining properties
* Operands: uint32_t nameIndex
* Stack: obj, val => obj
*/ \
MACRO(InitHiddenProp, init_hidden_prop, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPINIT|JOF_IC) \
/*
* Like `JSOp::InitProp`, but define a non-enumerable, non-writable,
* non-configurable property.
*
* This is used to define the `.prototype` property on classes.
*
* Implements: [MakeConstructor][1], step 8, when *writablePrototype* is
* false.
*
* [1]: https://tc39.es/ecma262/#sec-makeconstructor
*
* Category: Objects
* Type: Defining properties
* Operands: uint32_t nameIndex
* Stack: obj, val => obj
*/ \
MACRO(InitLockedProp, init_locked_prop, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPINIT|JOF_IC) \
/*
* Define a data property on `obj` with property key `id` and value `val`.
*
* `obj` must be an object.
*
* Implements: [CreateDataPropertyOrThrow][1]. This instruction is used for
* object literals like `{0: val}` and `{[id]: val}`, and methods like
* `*[Symbol.iterator]() {}`.
*
* `JSOp::InitHiddenElem` is the same but defines a non-enumerable property,
* for class methods.
* `JSOp::InitLockedElem` is the same but defines a non-enumerable, non-writable, non-configurable property,
* for private class methods.
*
* [1]: https://tc39.es/ecma262/#sec-createdatapropertyorthrow
*
* Category: Objects
* Type: Defining properties
* Operands:
* Stack: obj, id, val => obj
*/ \
MACRO(InitElem, init_elem, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPINIT|JOF_IC) \
MACRO(InitHiddenElem, init_hidden_elem, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPINIT|JOF_IC) \
MACRO(InitLockedElem, init_locked_elem, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPINIT|JOF_IC) \
/*
* Define an accessor property on `obj` with the given `getter`.
* `nameIndex` gives the property name.
*
* `obj` must be an object and `getter` must be a function.
*
* `JSOp::InitHiddenPropGetter` is the same but defines a non-enumerable
* property, for getters in classes.
*
* Category: Objects
* Type: Defining properties
* Operands: uint32_t nameIndex
* Stack: obj, getter => obj
*/ \
MACRO(InitPropGetter, init_prop_getter, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPINIT) \
MACRO(InitHiddenPropGetter, init_hidden_prop_getter, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPINIT) \
/*
* Define an accessor property on `obj` with property key `id` and the given `getter`.
*
* This is used to implement getters like `get [id]() {}` or `get 0() {}`.
*
* `obj` must be an object and `getter` must be a function.
*
* `JSOp::InitHiddenElemGetter` is the same but defines a non-enumerable
* property, for getters in classes.
*
* Category: Objects
* Type: Defining properties
* Operands:
* Stack: obj, id, getter => obj
*/ \
MACRO(InitElemGetter, init_elem_getter, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPINIT) \
MACRO(InitHiddenElemGetter, init_hidden_elem_getter, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPINIT) \
/*
* Define an accessor property on `obj` with the given `setter`.
*
* This is used to implement ordinary setters like `set foo(v) {}`.
*
* `obj` must be an object and `setter` must be a function.
*
* `JSOp::InitHiddenPropSetter` is the same but defines a non-enumerable
* property, for setters in classes.
*
* Category: Objects
* Type: Defining properties
* Operands: uint32_t nameIndex
* Stack: obj, setter => obj
*/ \
MACRO(InitPropSetter, init_prop_setter, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPINIT) \
MACRO(InitHiddenPropSetter, init_hidden_prop_setter, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPINIT) \
/*
* Define an accesssor property on `obj` with property key `id` and the
* given `setter`.
*
* This is used to implement setters with computed property keys or numeric
* keys.
*
* `JSOp::InitHiddenElemSetter` is the same but defines a non-enumerable
* property, for setters in classes.
*
* Category: Objects
* Type: Defining properties
* Operands:
* Stack: obj, id, setter => obj
*/ \
MACRO(InitElemSetter, init_elem_setter, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPINIT) \
MACRO(InitHiddenElemSetter, init_hidden_elem_setter, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPINIT) \
/*
* Get the value of the property `obj.name`. This can call getters and
* proxy traps.
*
* Implements: [GetV][1], [GetValue][2] step 5.
*
* [1]: https://tc39.es/ecma262/#sec-getv
* [2]: https://tc39.es/ecma262/#sec-getvalue
*
* Category: Objects
* Type: Accessing properties
* Operands: uint32_t nameIndex
* Stack: obj => obj[name]
*/ \
MACRO(GetProp, get_prop, NULL, 5, 1, 1, JOF_ATOM|JOF_PROP|JOF_IC) \
/*
* Get the value of the property `obj[key]`.
*
* Implements: [GetV][1], [GetValue][2] step 5.
*
* [1]: https://tc39.es/ecma262/#sec-getv
* [2]: https://tc39.es/ecma262/#sec-getvalue
*
* Category: Objects
* Type: Accessing properties
* Operands:
* Stack: obj, key => obj[key]
*/ \
MACRO(GetElem, get_elem, NULL, 1, 2, 1, JOF_BYTE|JOF_ELEM|JOF_IC) \
/*
* Non-strict assignment to a property, `obj.name = val`.
*
* This throws a TypeError if `obj` is null or undefined. If it's a
* primitive value, the property is set on ToObject(`obj`), typically with
* no effect.
*
* Implements: [PutValue][1] step 6 for non-strict code.
*
* [1]: https://tc39.es/ecma262/#sec-putvalue
*
* Category: Objects
* Type: Accessing properties
* Operands: uint32_t nameIndex
* Stack: obj, val => val
*/ \
MACRO(SetProp, set_prop, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPSET|JOF_CHECKSLOPPY|JOF_IC) \
/*
* Like `JSOp::SetProp`, but for strict mode code. Throw a TypeError if
* `obj[key]` exists but is non-writable, if it's an accessor property with
* no setter, or if `obj` is a primitive value.
*
* Category: Objects
* Type: Accessing properties
* Operands: uint32_t nameIndex
* Stack: obj, val => val
*/ \
MACRO(StrictSetProp, strict_set_prop, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_PROPSET|JOF_CHECKSTRICT|JOF_IC) \
/*
* Non-strict assignment to a property, `obj[key] = val`.
*
* Implements: [PutValue][1] step 6 for non-strict code.
*
* [1]: https://tc39.es/ecma262/#sec-putvalue
*
* Category: Objects
* Type: Accessing properties
* Operands:
* Stack: obj, key, val => val
*/ \
MACRO(SetElem, set_elem, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPSET|JOF_CHECKSLOPPY|JOF_IC) \
/*
* Like `JSOp::SetElem`, but for strict mode code. Throw a TypeError if
* `obj[key]` exists but is non-writable, if it's an accessor property with
* no setter, or if `obj` is a primitive value.
*
* Category: Objects
* Type: Accessing properties
* Operands:
* Stack: obj, key, val => val
*/ \
MACRO(StrictSetElem, strict_set_elem, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_PROPSET|JOF_CHECKSTRICT|JOF_IC) \
/*
* Delete a property from `obj`. Push true on success, false if the
* property existed but could not be deleted. This implements `delete
* obj.name` in non-strict code.
*
* Throws if `obj` is null or undefined. Can call proxy traps.
*
* Implements: [`delete obj.propname`][1] step 5 in non-strict code.
*
* [1]: https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
*
* Category: Objects
* Type: Accessing properties
* Operands: uint32_t nameIndex
* Stack: obj => succeeded
*/ \
MACRO(DelProp, del_prop, NULL, 5, 1, 1, JOF_ATOM|JOF_PROP|JOF_CHECKSLOPPY) \
/*
* Like `JSOp::DelProp`, but for strict mode code. Push `true` on success,
* else throw a TypeError.
*
* Category: Objects
* Type: Accessing properties
* Operands: uint32_t nameIndex
* Stack: obj => succeeded
*/ \
MACRO(StrictDelProp, strict_del_prop, NULL, 5, 1, 1, JOF_ATOM|JOF_PROP|JOF_CHECKSTRICT) \
/*
* Delete the property `obj[key]` and push `true` on success, `false`
* if the property existed but could not be deleted.
*
* This throws if `obj` is null or undefined. Can call proxy traps.
*
* Implements: [`delete obj[key]`][1] step 5 in non-strict code.
*
* [1]: https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
*
* Category: Objects
* Type: Accessing properties
* Operands:
* Stack: obj, key => succeeded
*/ \
MACRO(DelElem, del_elem, NULL, 1, 2, 1, JOF_BYTE|JOF_ELEM|JOF_CHECKSLOPPY) \
/*
* Like `JSOp::DelElem, but for strict mode code. Push `true` on success,
* else throw a TypeError.
*
* Category: Objects
* Type: Accessing properties
* Operands:
* Stack: obj, key => succeeded
*/ \
MACRO(StrictDelElem, strict_del_elem, NULL, 1, 2, 1, JOF_BYTE|JOF_ELEM|JOF_CHECKSTRICT) \
/*
* Push true if `obj` has an own property `id`.
*
* Note that `obj` is the top value, like `JSOp::In`.
*
* This opcode is not used for normal JS. Self-hosted code uses it by
* calling the intrinsic `hasOwn(id, obj)`. For example,
* `Object.prototype.hasOwnProperty` is implemented this way (see
* js/src/builtin/Object.js).
*
* Category: Objects
* Type: Accessing properties
* Operands:
* Stack: id, obj => (obj.hasOwnProperty(id))
*/ \
MACRO(HasOwn, has_own, NULL, 1, 2, 1, JOF_BYTE|JOF_IC) \
/*
* Push a bool representing the presence of private field id on obj.
* May throw, depending on the ThrowCondition.
*
* Two arguments:
* - throwCondition: One of the ThrowConditions defined in
* ThrowMsgKind.h. Determines why (or if) this op will throw.
* - msgKind: One of the ThrowMsgKinds defined in ThrowMsgKind.h, which
* maps to one of the messages in js.msg. Note: It's not possible to
* pass arguments to the message at the moment.
*
* Category: Objects
* Type: Accessing properties
* Operands: ThrowCondition throwCondition, ThrowMsgKind msgKind
* Stack: obj, key => obj, key, (obj.hasOwnProperty(id))
*/ \
MACRO(CheckPrivateField, check_private_field, NULL, 3, 2, 3, JOF_TWO_UINT8|JOF_CHECKSTRICT|JOF_IC) \
/*
* Push a new private name.
*
* Category: Objects
* Type: Accessing properties
* Operands: uint32_t nameIndex
* Stack: => private_name
*/ \
MACRO(NewPrivateName, new_private_name, NULL, 5, 0, 1, JOF_ATOM) \
/*
* Push the SuperBase of the method `callee`. The SuperBase is
* `callee.[[HomeObject]].[[GetPrototypeOf]]()`, the object where `super`
* property lookups should begin.
*
* `callee` must be a function that has a HomeObject that's an object,
* typically produced by `JSOp::Callee` or `JSOp::EnvCallee`.
*
* Implements: [GetSuperBase][1], except that instead of the environment,
* the argument supplies the callee.
*
* [1]: https://tc39.es/ecma262/#sec-getsuperbase
*
* Category: Objects
* Type: Super
* Operands:
* Stack: callee => superBase
*/ \
MACRO(SuperBase, super_base, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Get the value of `receiver.name`, starting the property search at `obj`.
* In spec terms, `obj.[[Get]](name, receiver)`.
*
* Implements: [GetValue][1] for references created by [`super.name`][2].
* The `receiver` is `this` and `obj` is the SuperBase of the enclosing
* method.
*
* [1]: https://tc39.es/ecma262/#sec-getvalue
* [2]: https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
*
* Category: Objects
* Type: Super
* Operands: uint32_t nameIndex
* Stack: receiver, obj => super.name
*/ \
MACRO(GetPropSuper, get_prop_super, NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_IC) \
/*
* Get the value of `receiver[key]`, starting the property search at `obj`.
* In spec terms, `obj.[[Get]](key, receiver)`.
*
* Implements: [GetValue][1] for references created by [`super[key]`][2]
* (where the `receiver` is `this` and `obj` is the SuperBase of the enclosing
* method); [`Reflect.get(obj, key, receiver)`][3].
*
* [1]: https://tc39.es/ecma262/#sec-getvalue
* [2]: https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
* [3]: https://tc39.es/ecma262/#sec-reflect.get
*
* Category: Objects
* Type: Super
* Operands:
* Stack: receiver, key, obj => super[key]
*/ \
MACRO(GetElemSuper, get_elem_super, NULL, 1, 3, 1, JOF_BYTE|JOF_ELEM|JOF_IC) \
/*
* Assign `val` to `receiver.name`, starting the search for an existing
* property at `obj`. In spec terms, `obj.[[Set]](name, val, receiver)`.
*
* Implements: [PutValue][1] for references created by [`super.name`][2] in
* non-strict code. The `receiver` is `this` and `obj` is the SuperBase of
* the enclosing method.
*
* [1]: https://tc39.es/ecma262/#sec-putvalue
* [2]: https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
*
* Category: Objects
* Type: Super
* Operands: uint32_t nameIndex
* Stack: receiver, obj, val => val
*/ \
MACRO(SetPropSuper, set_prop_super, NULL, 5, 3, 1, JOF_ATOM|JOF_PROP|JOF_PROPSET|JOF_CHECKSLOPPY) \
/*
* Like `JSOp::SetPropSuper`, but for strict mode code.
*
* Category: Objects
* Type: Super
* Operands: uint32_t nameIndex
* Stack: receiver, obj, val => val
*/ \
MACRO(StrictSetPropSuper, strict_set_prop_super, NULL, 5, 3, 1, JOF_ATOM|JOF_PROP|JOF_PROPSET|JOF_CHECKSTRICT) \
/*
* Assign `val` to `receiver[key]`, strating the search for an existing
* property at `obj`. In spec terms, `obj.[[Set]](key, val, receiver)`.
*
* Implements: [PutValue][1] for references created by [`super[key]`][2] in
* non-strict code. The `receiver` is `this` and `obj` is the SuperBase of
* the enclosing method.
*
* [1]: https://tc39.es/ecma262/#sec-putvalue
* [2]: https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
*
* Category: Objects
* Type: Super
* Operands:
* Stack: receiver, key, obj, val => val
*/ \
MACRO(SetElemSuper, set_elem_super, NULL, 1, 4, 1, JOF_BYTE|JOF_ELEM|JOF_PROPSET|JOF_CHECKSLOPPY) \
/*
* Like `JSOp::SetElemSuper`, but for strict mode code.
*
* Category: Objects
* Type: Super
* Operands:
* Stack: receiver, key, obj, val => val
*/ \
MACRO(StrictSetElemSuper, strict_set_elem_super, NULL, 1, 4, 1, JOF_BYTE|JOF_ELEM|JOF_PROPSET|JOF_CHECKSTRICT) \
/*
* Set up a for-in loop by pushing a `PropertyIteratorObject` over the
* enumerable properties of `val`.
*
* Implements: [ForIn/OfHeadEvaluation][1] step 6,
* [EnumerateObjectProperties][1]. (The spec refers to an "Iterator object"
* with a `next` method, but notes that it "is never directly accessible"
* to scripts. The object we use for this has no public methods.)
*
* If `val` is null or undefined, this pushes an empty iterator.
*
* The `iter` object pushed by this instruction must not be used or removed
* from the stack except by `JSOp::MoreIter` and `JSOp::EndIter`, or by error
* handling.
*
* The script's `JSScript::trynotes()` must mark the body of the `for-in`
* loop, i.e. exactly those instructions that begin executing with `iter`
* on the stack, starting with the next instruction (always
* `JSOp::LoopHead`). Code must not jump into or out of this region: control
* can enter only by executing `JSOp::Iter` and can exit only by executing a
* `JSOp::EndIter` or by exception unwinding. (A `JSOp::EndIter` is always
* emitted at the end of the loop, and extra copies are emitted on "exit
* slides", where a `break`, `continue`, or `return` statement exits the
* loop.)
*
* Typically a single try note entry marks the contiguous chunk of bytecode
* from the instruction after `JSOp::Iter` to `JSOp::EndIter` (inclusive);
* but if that range contains any instructions on exit slides, after a
* `JSOp::EndIter`, then those must be correctly noted as *outside* the
* loop.
*
* [1]: https://tc39.es/ecma262/#sec-runtime-semantics-forin-div-ofheadevaluation-tdznames-expr-iterationkind
* [2]: https://tc39.es/ecma262/#sec-enumerate-object-properties
*
* Category: Objects
* Type: Enumeration
* Operands:
* Stack: val => iter
*/ \
MACRO(Iter, iter, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* Get the next property name for a for-in loop.
*
* `iter` must be a `PropertyIteratorObject` produced by `JSOp::Iter`. This
* pushes the property name for the next loop iteration, or
* `MagicValue(JS_NO_ITER_VALUE)` if there are no more enumerable
* properties to iterate over. The magic value must be used only by
* `JSOp::IsNoIter` and `JSOp::EndIter`.
*
* Category: Objects
* Type: Enumeration
* Operands:
* Stack: iter => iter, name
*/ \
MACRO(MoreIter, more_iter, NULL, 1, 1, 2, JOF_BYTE) \
/*
* Test whether the value on top of the stack is
* `MagicValue(JS_NO_ITER_VALUE)` and push the boolean result.
*
* Category: Objects
* Type: Enumeration
* Operands:
* Stack: val => val, done
*/ \
MACRO(IsNoIter, is_no_iter, NULL, 1, 1, 2, JOF_BYTE) \
/*
* Exit a for-in loop, closing the iterator.
*
* `iter` must be a `PropertyIteratorObject` pushed by `JSOp::Iter`.
*
* Category: Objects
* Type: Enumeration
* Operands:
* Stack: iter, iterval =>
*/ \
MACRO(EndIter, end_iter, NULL, 1, 2, 0, JOF_BYTE) \
/*
* If the iterator object on top of the stack has a `return` method,
* call that method. If the method exists but does not return an object,
* and `kind` is not `CompletionKind::Throw`, throw a TypeError. (If
* `kind` is `Throw`, the error we are already throwing takes precedence.)
*
* `iter` must be an object conforming to the [Iterator][1] interface.
*
* Implements: [IteratorClose][2]
*
* [1]: https://tc39.es/ecma262/#sec-iterator-interface
* [2]: https://tc39.es/ecma262/#sec-iteratorclose
* Category: Objects
* Type: Iteration
* Operands: CompletionKind kind
* Stack: iter =>
*/ \
MACRO(CloseIter, close_iter, NULL, 2, 1, 0, JOF_UINT8|JOF_IC) \
/*
* Check that the top value on the stack is an object, and throw a
* TypeError if not. `kind` is used only to generate an appropriate error
* message.
*
* Implements: [GetIterator][1] step 5, [IteratorNext][2] step 3. Both
* operations call a JS method which scripts can define however they want,
* so they check afterwards that the method returned an object.
*
* [1]: https://tc39.es/ecma262/#sec-getiterator
* [2]: https://tc39.es/ecma262/#sec-iteratornext
*
* Category: Objects
* Type: Iteration
* Operands: CheckIsObjectKind kind
* Stack: result => result
*/ \
MACRO(CheckIsObj, check_is_obj, NULL, 2, 1, 1, JOF_UINT8) \
/*
* Throw a TypeError if `val` is `null` or `undefined`.
*
* Implements: [RequireObjectCoercible][1]. But most instructions that
* require an object will perform this check for us, so of the dozens of
* calls to RequireObjectCoercible in the spec, we need this instruction
* only for [destructuring assignment][2] and [initialization][3].
*
* [1]: https://tc39.es/ecma262/#sec-requireobjectcoercible
* [2]: https://tc39.es/ecma262/#sec-runtime-semantics-destructuringassignmentevaluation
* [3]: https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-bindinginitialization
*
* Category: Objects
* Type: Iteration
* Operands:
* Stack: val => val
*/ \
MACRO(CheckObjCoercible, check_obj_coercible, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Create and push an async iterator wrapping the sync iterator `iter`.
* `next` should be `iter`'s `.next` method.
*
* Implements: [CreateAsyncToSyncIterator][1]. The spec says this operation
* takes one argument, but that argument is a Record with two relevant
* fields, `[[Iterator]]` and `[[NextMethod]]`.
*
* Used for `for await` loops.
*
* [1]: https://tc39.es/ecma262/#sec-createasyncfromsynciterator
*
* Category: Objects
* Type: Iteration
* Operands:
* Stack: iter, next => asynciter
*/ \
MACRO(ToAsyncIter, to_async_iter, NULL, 1, 2, 1, JOF_BYTE) \
/*
* Set the prototype of `obj`.
*
* `obj` must be an object.
*
* Implements: [B.3.1 __proto__ Property Names in Object Initializers][1], step 7.a.
*
* [1]: https://tc39.es/ecma262/#sec-__proto__-property-names-in-object-initializers
*
* Category: Objects
* Type: SetPrototype
* Operands:
* Stack: obj, protoVal => obj
*/ \
MACRO(MutateProto, mutate_proto, NULL, 1, 2, 1, JOF_BYTE) \
/*
* Create and push a new Array object with the given `length`,
* preallocating enough memory to hold that many elements.
*
* Category: Objects
* Type: Array literals
* Operands: uint32_t length
* Stack: => array
*/ \
MACRO(NewArray, new_array, NULL, 5, 0, 1, JOF_UINT32|JOF_IC) \
/*
* Initialize an array element `array[index]` with value `val`.
*
* `val` may be `MagicValue(JS_ELEMENTS_HOLE)` pushed by `JSOp::Hole`.
*
* This never calls setters or proxy traps.
*
* `array` must be an Array object created by `JSOp::NewArray` with length >
* `index`, and never used except by `JSOp::InitElemArray`.
*
* Implements: [ArrayAccumulation][1], the third algorithm, step 4, in the
* common case where *nextIndex* is known.
*
* [1]: https://tc39.es/ecma262/#sec-runtime-semantics-arrayaccumulation
*
* Category: Objects
* Type: Array literals
* Operands: uint32_t index
* Stack: array, val => array
*/ \
MACRO(InitElemArray, init_elem_array, NULL, 5, 2, 1, JOF_UINT32|JOF_ELEM|JOF_PROPINIT) \
/*
* Initialize an array element `array[index++]` with value `val`.
*
* `val` may be `MagicValue(JS_ELEMENTS_HOLE)` pushed by `JSOp::Hole`. If it
* is, no element is defined, but the array length and the stack value
* `index` are still incremented.
*
* This never calls setters or proxy traps.
*
* `array` must be an Array object created by `JSOp::NewArray` and never used
* except by `JSOp::InitElemArray` and `JSOp::InitElemInc`.
*
* `index` must be an integer, `0 <= index <= INT32_MAX`. If `index` is
* `INT32_MAX`, this throws a RangeError.
*
* This instruction is used when an array literal contains a
* *SpreadElement*. In `[a, ...b, c]`, `InitElemArray 0` is used to put
* `a` into the array, but `InitElemInc` is used for the elements of `b`
* and for `c`.
*
* Implements: Several steps in [ArrayAccumulation][1] that call
* CreateDataProperty, set the array length, and/or increment *nextIndex*.
*
* [1]: https://tc39.es/ecma262/#sec-runtime-semantics-arrayaccumulation
*
* Category: Objects
* Type: Array literals
* Operands:
* Stack: array, index, val => array, (index + 1)
*/ \
MACRO(InitElemInc, init_elem_inc, NULL, 1, 3, 2, JOF_BYTE|JOF_ELEM|JOF_PROPINIT|JOF_IC) \
/*
* Push `MagicValue(JS_ELEMENTS_HOLE)`, representing an *Elision* in an
* array literal (like the missing property 0 in the array `[, 1]`).
*
* This magic value must be used only by `JSOp::InitElemArray` or
* `JSOp::InitElemInc`.
*
* Category: Objects
* Type: Array literals
* Operands:
* Stack: => hole
*/ \
MACRO(Hole, hole, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Clone and push a new RegExp object.
*
* Implements: [Evaluation for *RegularExpressionLiteral*][1].
*
* [1]: https://tc39.es/ecma262/#sec-regular-expression-literals-runtime-semantics-evaluation
*
* Category: Objects
* Type: RegExp literals
* Operands: uint32_t regexpIndex
* Stack: => regexp
*/ \
MACRO(RegExp, reg_exp, NULL, 5, 0, 1, JOF_REGEXP) \
/*
* Initialize a new record, preallocating `length` memory slots. `length` can still grow
* if needed, for example when using the spread operator.
*
* Implements: [RecordLiteral Evaluation][1] step 1.
*
* [1]: https://tc39.es/proposal-record-tuple/#sec-record-initializer-runtime-semantics-evaluation
*
* Category: Compound primitives
* Type: Record literals
* Operands: uint32_t length
* Stack: => rval
*/ \
IF_RECORD_TUPLE(MACRO(InitRecord, init_record, NULL, 5, 0, 1, JOF_UINT32)) \
/*
* Add the last element in the stack to the preceding tuple.
*
* Implements: [AddPropertyIntoRecordEntriesList][1].
*
* [1]: https://tc39.es/proposal-record-tuple/#sec-addpropertyintorecordentrieslist
*
* Category: Compound primitives
* Type: Record literals
* Operands:
* Stack: record, key, value => record
*/ \
IF_RECORD_TUPLE(MACRO(AddRecordProperty, add_record_property, NULL, 1, 3, 1, JOF_BYTE)) \
/*
* Add the last element in the stack to the preceding tuple.
*
* Implements: [RecordPropertyDefinitionEvaluation][1] for
* RecordPropertyDefinition : ... AssignmentExpression
*
* [1]: https://tc39.es/proposal-record-tuple/#sec-addpropertyintorecordentrieslist
*
* Category: Compound primitives
* Type: Record literals
* Operands:
* Stack: record, value => record
*/ \
IF_RECORD_TUPLE(MACRO(AddRecordSpread, add_record_spread, NULL, 1, 2, 1, JOF_BYTE)) \
/*
* Mark a record as "initialized", going from "write-only" mode to
* "read-only" mode.
*
* Category: Compound primitives
* Type: Record literals
* Operands:
* Stack: record => record
*/ \
IF_RECORD_TUPLE(MACRO(FinishRecord, finish_record, NULL, 1, 1, 1, JOF_BYTE)) \
/*
* Initialize a new tuple, preallocating `length` memory slots. `length` can still grow
* if needed, for example when using the spread operator.
*
* Implements: [TupleLiteral Evaluation][1] step 1.
*
* [1]: https://tc39.es/proposal-record-tuple/#sec-tuple-initializer-runtime-semantics-evaluation
*
* Category: Compound primitives
* Type: Tuple literals
* Operands: uint32_t length
* Stack: => rval
*/ \
IF_RECORD_TUPLE(MACRO(InitTuple, init_tuple, NULL, 5, 0, 1, JOF_UINT32)) \
/*
* Add the last element in the stack to the preceding tuple.
*
* Implements: [AddValueToTupleSequenceList][1].
*
* [1]: https://tc39.es/proposal-record-tuple/#sec-addvaluetotuplesequencelist
*
* Category: Compound primitives
* Type: Tuple literals
* Operands:
* Stack: tuple, element => tuple
*/ \
IF_RECORD_TUPLE(MACRO(AddTupleElement, add_tuple_element, NULL, 1, 2, 1, JOF_BYTE)) \
/*
* Mark a tuple as "initialized", going from "write-only" mode to
* "read-only" mode.
*
* Category: Compound primitives
* Type: Tuple literals
* Operands:
* Stack: tuple => tuple
*/ \
IF_RECORD_TUPLE(MACRO(FinishTuple, finish_tuple, NULL, 1, 1, 1, JOF_BYTE)) \
/*
* Push a new function object.
*
* The new function inherits the current environment chain.
*
* Used to create most JS functions. Notable exceptions are derived or
* default class constructors.
*
* Implements: [InstantiateFunctionObject][1], [Evaluation for
* *FunctionExpression*][2], and so on.
*
* [1]: https://tc39.es/ecma262/#sec-function-definitions-runtime-semantics-instantiatefunctionobject
* [2]: https://tc39.es/ecma262/#sec-function-definitions-runtime-semantics-evaluation
*
* Category: Functions
* Type: Creating functions
* Operands: uint32_t funcIndex
* Stack: => fn
*/ \
MACRO(Lambda, lambda, NULL, 5, 0, 1, JOF_OBJECT) \
/*
* Set the name of a function.
*
* `fun` must be a function object. `name` must be a string, Int32 value,
* or symbol (like the result of `JSOp::ToId`).
*
* Implements: [SetFunctionName][1], used e.g. to name methods with
* computed property names.
*
* [1]: https://tc39.es/ecma262/#sec-setfunctionname
*
* Category: Functions
* Type: Creating functions
* Operands: FunctionPrefixKind prefixKind
* Stack: fun, name => fun
*/ \
MACRO(SetFunName, set_fun_name, NULL, 2, 2, 1, JOF_UINT8) \
/*
* Initialize the home object for functions with super bindings.
*
* `fun` must be a method, getter, or setter, so that it has a
* [[HomeObject]] slot. `homeObject` must be a plain object or (for static
* methods) a constructor.
*
* Category: Functions
* Type: Creating functions
* Operands:
* Stack: fun, homeObject => fun
*/ \
MACRO(InitHomeObject, init_home_object, NULL, 1, 2, 1, JOF_BYTE) \
/*
* Throw a TypeError if `baseClass` isn't either `null` or a constructor.
*
* Implements: [ClassDefinitionEvaluation][1] step 6.f.
*
* [1]: https://tc39.es/ecma262/#sec-runtime-semantics-classdefinitionevaluation
*
* Category: Functions
* Type: Creating constructors
* Operands:
* Stack: baseClass => baseClass
*/ \
MACRO(CheckClassHeritage, check_class_heritage, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Like `JSOp::Lambda`, but using `proto` as the new function's
* `[[Prototype]]` (or `%FunctionPrototype%` if `proto` is `null`).
*
* `proto` must be either a constructor or `null`. We use
* `JSOp::CheckClassHeritage` to check.
*
* This is used to create the constructor for a derived class.
*
* Implements: [ClassDefinitionEvaluation][1] steps 6.e.ii, 6.g.iii, and
* 12 for derived classes.
*
* [1]: https://tc39.es/ecma262/#sec-runtime-semantics-classdefinitionevaluation
*
* Category: Functions
* Type: Creating constructors
* Operands: uint32_t funcIndex
* Stack: proto => obj
*/ \
MACRO(FunWithProto, fun_with_proto, NULL, 5, 1, 1, JOF_OBJECT) \
/*
* Pushes the current global's %BuiltinObject%.
*
* `kind` must be a valid `BuiltinObjectKind` (and must not be
* `BuiltinObjectKind::None`).
*
* Category: Objects
* Type: Built-in objects
* Operands: uint8_t kind
* Stack: => %BuiltinObject%
*/ \
MACRO(BuiltinObject, builtin_object, NULL, 2, 0, 1, JOF_UINT8) \
/*
* Invoke `callee` with `this` and `args`, and push the return value. Throw
* a TypeError if `callee` isn't a function.
*
* `JSOp::CallContent` is for `callContentFunction` in self-hosted JS, and
* this is for handling it differently in debugger's `onNativeCall` hook.
* `onNativeCall` hook disables all JITs, and `JSOp::CallContent` is
* treated exactly the same as `JSOP::Call` in JIT.
*
* `JSOp::CallIter` is used for implicit calls to @@iterator methods, to
* ensure error messages are formatted with `JSMSG_NOT_ITERABLE` ("x is not
* iterable") rather than `JSMSG_NOT_FUNCTION` ("x[Symbol.iterator] is not
* a function"). The `argc` operand must be 0 for this variation.
*
* `JSOp::CallContentIter` is `JSOp::CallContent` variant of
* `JSOp::CallIter`.
*
* `JSOp::CallIgnoresRv` hints to the VM that the return value is ignored.
* This allows alternate faster implementations to be used that avoid
* unnecesary allocations.
*
* Implements: [EvaluateCall][1] steps 4, 5, and 7.
*
* [1]: https://tc39.es/ecma262/#sec-evaluatecall
*
* Category: Functions
* Type: Calls
* Operands: uint16_t argc
* Stack: callee, this, args[0], ..., args[argc-1] => rval
*/ \
MACRO(Call, call, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_IC) \
MACRO(CallContent, call_content, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_IC) \
MACRO(CallIter, call_iter, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_IC) \
MACRO(CallContentIter, call_content_iter, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_IC) \
MACRO(CallIgnoresRv, call_ignores_rv, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_IC) \
/*
* Like `JSOp::Call`, but the arguments are provided in an array rather than
* a span of stack slots. Used to implement spread-call syntax:
* `f(...args)`.
*
* `args` must be an Array object containing the actual arguments. The
* array must be packed (dense and free of holes; see IsPackedArray).
* This can be ensured by creating the array with `JSOp::NewArray` and
* populating it using `JSOp::InitElemArray`.
*
* Category: Functions
* Type: Calls
* Operands:
* Stack: callee, this, args => rval
*/ \
MACRO(SpreadCall, spread_call, NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_SPREAD|JOF_IC) \
/*
* Push an array object that can be passed directly as the `args` argument
* to `JSOp::SpreadCall`. If the operation can't be optimized, push
* `undefined` instead.
*
* This instruction and the branch around the iterator loop are emitted
* only when `iterable` is the sole argument in a call, as in `f(...arr)`.
*
* See `js::OptimizeSpreadCall`.
*
* Category: Functions
* Type: Calls
* Operands:
* Stack: iterable => array_or_undefined
*/ \
MACRO(OptimizeSpreadCall, optimize_spread_call, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
/*
* Perform a direct eval in the current environment if `callee` is the
* builtin `eval` function, otherwise follow same behaviour as `JSOp::Call`.
*
* All direct evals use one of the JSOp::*Eval instructions here and these
* opcodes are only used when the syntactic conditions for a direct eval
* are met. If the builtin `eval` function is called though other means, it
* becomes an indirect eval.
*
* Direct eval causes all bindings in *enclosing* non-global scopes to be
* marked "aliased". The optimization that puts bindings in stack slots has
* to prove that the bindings won't need to be captured by closures or
* accessed using `JSOp::{Get,Bind,Set,Del}Name` instructions. Direct eval
* makes that analysis impossible.
*
* The instruction immediately following any `JSOp::*Eval` instruction must
* be `JSOp::Lineno`.
*
* Implements: [Function Call Evaluation][1], steps 5-7 and 9, when the
* syntactic critera for direct eval in step 6 are all met.
*
* [1]: https://tc39.es/ecma262/#sec-function-calls-runtime-semantics-evaluation
*
* Category: Functions
* Type: Calls
* Operands: uint16_t argc
* Stack: callee, this, args[0], ..., args[argc-1] => rval
*/ \
MACRO(Eval, eval, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_CHECKSLOPPY|JOF_IC) \
/*
* Spread-call variant of `JSOp::Eval`.
*
* See `JSOp::SpreadCall` for restrictions on `args`.
*
* Category: Functions
* Type: Calls
* Operands:
* Stack: callee, this, args => rval
*/ \
MACRO(SpreadEval, spread_eval, NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_SPREAD|JOF_CHECKSLOPPY|JOF_IC) \
/*
* Like `JSOp::Eval`, but for strict mode code.
*
* Category: Functions
* Type: Calls
* Operands: uint16_t argc
* Stack: evalFn, this, args[0], ..., args[argc-1] => rval
*/ \
MACRO(StrictEval, strict_eval, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_CHECKSTRICT|JOF_IC) \
/*
* Spread-call variant of `JSOp::StrictEval`.
*
* See `JSOp::SpreadCall` for restrictions on `args`.
*
* Category: Functions
* Type: Calls
* Operands:
* Stack: callee, this, args => rval
*/ \
MACRO(StrictSpreadEval, strict_spread_eval, NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_SPREAD|JOF_CHECKSTRICT|JOF_IC) \
/*
* Push the implicit `this` value for an unqualified function call, like
* `foo()`. `nameIndex` gives the name of the function we're calling.
*
* The result is always `undefined` except when the name refers to a `with`
* binding. For example, in `with (date) { getFullYear(); }`, the
* implicit `this` passed to `getFullYear` is `date`, not `undefined`.
*
* This walks the run-time environment chain looking for the environment
* record that contains the function. If the function call definitely
* refers to a local binding, use `JSOp::Undefined`.
*
* Implements: [EvaluateCall][1] step 1.b. But not entirely correctly.
* See [bug 1166408][2].
*
* [1]: https://tc39.es/ecma262/#sec-evaluatecall
* [2]: https://bugzilla.mozilla.org/show_bug.cgi?id=1166408
*
* Category: Functions
* Type: Calls
* Operands: uint32_t nameIndex
* Stack: => this
*/ \
MACRO(ImplicitThis, implicit_this, "", 5, 0, 1, JOF_ATOM) \
/*
* Push the call site object for a tagged template call.
*
* `script->getObject(objectIndex)` is the call site object;
* `script->getObject(objectIndex + 1)` is the raw object.
*
* The first time this instruction runs for a given template, it assembles
* the final value, defining the `.raw` property on the call site object
* and freezing both objects.
*
* Implements: [GetTemplateObject][1], steps 4 and 12-16.
*
* [1]: https://tc39.es/ecma262/#sec-gettemplateobject
*
* Category: Functions
* Type: Calls
* Operands: uint32_t objectIndex
* Stack: => callSiteObj
*/ \
MACRO(CallSiteObj, call_site_obj, NULL, 5, 0, 1, JOF_OBJECT) \
/*
* Push `MagicValue(JS_IS_CONSTRUCTING)`.
*
* This magic value is a required argument to the `JSOp::New` and
* `JSOp::SuperCall` instructions and must not be used any other way.
*
* Category: Functions
* Type: Calls
* Operands:
* Stack: => JS_IS_CONSTRUCTING
*/ \
MACRO(IsConstructing, is_constructing, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Invoke `callee` as a constructor with `args` and `newTarget`, and push
* the return value. Throw a TypeError if `callee` isn't a constructor.
*
* `isConstructing` must be the value pushed by `JSOp::IsConstructing`.
*
* `JSOp::SuperCall` behaves exactly like `JSOp::New`, but is used for
* *SuperCall* expressions, to allow JITs to distinguish them from `new`
* expressions.
*
* `JSOp::NewContent` is for `constructContentFunction` in self-hosted JS.
* See the comment for `JSOp::CallContent` for more details.
*
* Implements: [EvaluateConstruct][1] steps 7 and 8.
*
* [1]: https://tc39.es/ecma262/#sec-evaluatenew
*
* Category: Functions
* Type: Calls
* Operands: uint16_t argc
* Stack: callee, isConstructing, args[0], ..., args[argc-1], newTarget => rval
*/ \
MACRO(New, new_, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_CONSTRUCT|JOF_IC) \
MACRO(NewContent, new_content, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_CONSTRUCT|JOF_IC) \
MACRO(SuperCall, super_call, NULL, 3, -1, 1, JOF_ARGC|JOF_INVOKE|JOF_CONSTRUCT|JOF_IC) \
/*
* Spread-call variant of `JSOp::New`.
*
* Invokes `callee` as a constructor with `args` and `newTarget`, and
* pushes the return value onto the stack.
*
* `isConstructing` must be the value pushed by `JSOp::IsConstructing`.
* See `JSOp::SpreadCall` for restrictions on `args`.
*
* `JSOp::SpreadSuperCall` behaves exactly like `JSOp::SpreadNew`, but is
* used for *SuperCall* expressions.
*
* Category: Functions
* Type: Calls
* Operands:
* Stack: callee, isConstructing, args, newTarget => rval
*/ \
MACRO(SpreadNew, spread_new, NULL, 1, 4, 1, JOF_BYTE|JOF_INVOKE|JOF_CONSTRUCT|JOF_SPREAD|JOF_IC) \
MACRO(SpreadSuperCall, spread_super_call, NULL, 1, 4, 1, JOF_BYTE|JOF_INVOKE|JOF_CONSTRUCT|JOF_SPREAD|JOF_IC) \
/*
* Push the prototype of `callee` in preparation for calling `super()`.
*
* `callee` must be a derived class constructor.
*
* Implements: [GetSuperConstructor][1], steps 4-7.
*
* [1]: https://tc39.es/ecma262/#sec-getsuperconstructor
*
* Category: Functions
* Type: Calls
* Operands:
* Stack: callee => superFun
*/ \
MACRO(SuperFun, super_fun, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Throw a ReferenceError if `thisval` is not
* `MagicValue(JS_UNINITIALIZED_LEXICAL)`. Used in derived class
* constructors to prohibit calling `super` more than once.
*
* Implements: [BindThisValue][1], step 3.
*
* [1]: https://tc39.es/ecma262/#sec-bindthisvalue
*
* Category: Functions
* Type: Calls
* Operands:
* Stack: thisval => thisval
*/ \
MACRO(CheckThisReinit, check_this_reinit, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Create and push a generator object for the current frame.
*
* This instruction must appear only in scripts for generators, async
* functions, and async generators. There must not already be a generator
* object for the current frame (that is, this instruction must execute at
* most once per generator or async call).
*
* Category: Functions
* Type: Generators and async functions
* Operands:
* Stack: => gen
*/ \
MACRO(Generator, generator, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Suspend the current generator and return to the caller.
*
* When a generator is called, its script starts running, like any other JS
* function, because [FunctionDeclarationInstantation][1] and other
* [generator object setup][2] are implemented mostly in bytecode. However,
* the *FunctionBody* of the generator is not supposed to start running
* until the first `.next()` call, so after setup the script suspends
* itself: the "initial yield".
*
* Later, when resuming execution, `rval`, `gen` and `resumeKind` will
* receive the values passed in by `JSOp::Resume`. `resumeKind` is the
* `GeneratorResumeKind` stored as an Int32 value.
*
* This instruction must appear only in scripts for generators and async
* generators. `gen` must be the generator object for the current frame. It
* must not have been previously suspended. The resume point indicated by
* `resumeIndex` must be the next instruction in the script, which must be
* `AfterYield`.
*
* Implements: [GeneratorStart][3], steps 4-7.
*
* [1]: https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
* [2]: https://tc39.es/ecma262/#sec-generator-function-definitions-runtime-semantics-evaluatebody
* [3]: https://tc39.es/ecma262/#sec-generatorstart
*
* Category: Functions
* Type: Generators and async functions
* Operands: uint24_t resumeIndex
* Stack: gen => rval, gen, resumeKind
*/ \
MACRO(InitialYield, initial_yield, NULL, 4, 1, 3, JOF_RESUMEINDEX) \
/*
* Bytecode emitted after `yield` expressions. This is useful for the
* Debugger and `AbstractGeneratorObject::isAfterYieldOrAwait`. It's
* treated as jump target op so that the Baseline Interpreter can
* efficiently restore the frame's interpreterICEntry when resuming a
* generator.
*
* The preceding instruction in the script must be `Yield`, `InitialYield`,
* or `Await`.
*
* Category: Functions
* Type: Generators and async functions
* Operands: uint32_t icIndex
* Stack: =>
*/ \
MACRO(AfterYield, after_yield, NULL, 5, 0, 0, JOF_ICINDEX) \
/*
* Suspend and close the current generator, async function, or async
* generator.
*
* `gen` must be the generator object for the current frame.
*
* If the current function is a non-async generator, then the value in the
* frame's return value slot is returned to the caller. It should be an
* object of the form `{value: returnValue, done: true}`.
*
* If the current function is an async function or async generator, the
* frame's return value slot must contain the current frame's result
* promise, which must already be resolved or rejected.
*
* Category: Functions
* Type: Generators and async functions
* Operands:
* Stack: gen =>
*/ \
MACRO(FinalYieldRval, final_yield_rval, NULL, 1, 1, 0, JOF_BYTE) \
/*
* Suspend execution of the current generator or async generator, returning
* `rval1`.
*
* For non-async generators, `rval1` should be an object of the form
* `{value: valueToYield, done: true}`. For async generators, `rval1`
* should be the value to yield, and the caller is responsible for creating
* the iterator result object (under `js::AsyncGeneratorYield`).
*
* This instruction must appear only in scripts for generators and async
* generators. `gen` must be the generator object for the current stack
* frame. The resume point indicated by `resumeIndex` must be the next
* instruction in the script, which must be `AfterYield`.
*
* When resuming execution, `rval2`, `gen` and `resumeKind` receive the
* values passed in by `JSOp::Resume`.
*
* Implements: [GeneratorYield][1] and [AsyncGeneratorYield][2].
*
* [1]: https://tc39.es/ecma262/#sec-generatoryield
* [2]: https://tc39.es/ecma262/#sec-asyncgeneratoryield
*
* Category: Functions
* Type: Generators and async functions
* Operands: uint24_t resumeIndex
* Stack: rval1, gen => rval2, gen, resumeKind
*/ \
MACRO(Yield, yield, NULL, 4, 2, 3, JOF_RESUMEINDEX) \
/*
* Pushes a boolean indicating whether the top of the stack is
* `MagicValue(JS_GENERATOR_CLOSING)`.
*
* Category: Functions
* Type: Generators and async functions
* Operands:
* Stack: val => val, res
*/ \
MACRO(IsGenClosing, is_gen_closing, NULL, 1, 1, 2, JOF_BYTE) \
/*
* Arrange for this async function to resume asynchronously when `value`
* becomes resolved.
*
* This is the last thing an async function does before suspending for an
* `await` expression. It coerces the awaited `value` to a promise and
* effectively calls `.then()` on it, passing handler functions that will
* resume this async function call later. See `js::AsyncFunctionAwait`.
*
* This instruction must appear only in non-generator async function
* scripts. `gen` must be the internal generator object for the current
* frame. After this instruction, the script should suspend itself with
* `Await` (rather than exiting any other way).
*
* The result `promise` is the async function's result promise,
* `gen->as<AsyncFunctionGeneratorObject>().promise()`.
*
* Implements: [Await][1], steps 2-9.
*
* [1]: https://tc39.github.io/ecma262/#await
*
* Category: Functions
* Type: Generators and async functions
* Operands:
* Stack: value, gen => promise
*/ \
MACRO(AsyncAwait, async_await, NULL, 1, 2, 1, JOF_BYTE) \
/*
* Resolve or reject the current async function's result promise with
* 'valueOrReason'.
*
* This instruction must appear only in non-generator async function
* scripts. `gen` must be the internal generator object for the current
* frame. This instruction must run at most once per async function call,
* as resolving/rejecting an already resolved/rejected promise is not
* permitted.
*
* The result `promise` is the async function's result promise,
* `gen->as<AsyncFunctionGeneratorObject>().promise()`.
*
* Implements: [AsyncFunctionStart][1], step 4.d.i. and 4.e.i.
*
* [1]: https://tc39.es/ecma262/#sec-async-functions-abstract-operations-async-function-start
*
* Category: Functions
* Type: Generators and async functions
* Operands: AsyncFunctionResolveKind fulfillOrReject
* Stack: valueOrReason, gen => promise
*/ \
MACRO(AsyncResolve, async_resolve, NULL, 2, 2, 1, JOF_UINT8) \
/*
* Suspend the current frame for an `await` expression.
*
* This instruction must appear only in scripts for async functions and
* async generators. `gen` must be the internal generator object for the
* current frame.
*
* This returns `promise` to the caller. Later, when this async call is
* resumed, `resolved`, `gen` and `resumeKind` receive the values passed in
* by `JSOp::Resume`, and execution continues at the next instruction,
* which must be `AfterYield`.
*
* This instruction is used in two subtly different ways.
*
* 1. In async functions:
*
* ... # valueToAwait
* GetAliasedVar ".generator" # valueToAwait gen
* AsyncAwait # resultPromise
* GetAliasedVar ".generator" # resultPromise gen
* Await # resolved gen resumeKind
* AfterYield
*
* `AsyncAwait` arranges for this frame to be resumed later and pushes
* its result promise. `Await` then suspends the frame and removes it
* from the stack, returning the result promise to the caller. (If this
* async call hasn't awaited before, the caller may be user code.
* Otherwise, the caller is self-hosted code using `resumeGenerator`.)
*
* 2. In async generators:
*
* ... # valueToAwait
* GetAliasedVar ".generator" # valueToAwait gen
* Await # resolved gen resumeKind
* AfterYield
*
* `AsyncAwait` is not used, so (1) the value returned to the caller by
* `Await` is `valueToAwait`, not `resultPromise`; and (2) the caller
* is responsible for doing the async-generator equivalent of
* `AsyncAwait` (namely, `js::AsyncGeneratorAwait`, called from
* `js::AsyncGeneratorResume` after `js::CallSelfHostedFunction`
* returns).
*
* Implements: [Await][1], steps 10-12.
*
* [1]: https://tc39.es/ecma262/#await
*
* Category: Functions
* Type: Generators and async functions
* Operands: uint24_t resumeIndex
* Stack: promise, gen => resolved, gen, resumeKind
*/ \
MACRO(Await, await, NULL, 4, 2, 3, JOF_RESUMEINDEX) \
/*
* Test if the re-entry to the microtask loop may be skipped.
*
* This is part of an optimization for `await` expressions. Programs very
* often await values that aren't promises, or promises that are already
* resolved. We can then sometimes skip suspending the current frame and
* returning to the microtask loop. If the circumstances permit the
* optimization, `CanSkipAwait` pushes true if the optimization is allowed,
* and false otherwise.
*
* Category: Functions
* Type: Generators and async functions
* Operands:
* Stack: value => value, can_skip
*/ \
MACRO(CanSkipAwait, can_skip_await, NULL, 1, 1, 2, JOF_BYTE) \
/*
* Potentially extract an awaited value, if the await is skippable
*
* If re-entering the microtask loop is skippable (as checked by CanSkipAwait)
* if can_skip is true, `MaybeExtractAwaitValue` replaces `value` with the result of the
* `await` expression (unwrapping the resolved promise, if any). Otherwise, value remains
* as is.
*
* In both cases, can_skip remains the same.
*
* Category: Functions
* Type: Generators and async functions
* Operands:
* Stack: value, can_skip => value_or_resolved, can_skip
*/ \
MACRO(MaybeExtractAwaitValue, maybe_extract_await_value, NULL, 1, 2, 2, JOF_BYTE) \
/*
* Pushes one of the GeneratorResumeKind values as Int32Value.
*
* Category: Functions
* Type: Generators and async functions
* Operands: GeneratorResumeKind resumeKind (encoded as uint8_t)
* Stack: => resumeKind
*/ \
MACRO(ResumeKind, resume_kind, NULL, 2, 0, 1, JOF_UINT8) \
/*
* Handle Throw and Return resumption.
*
* `gen` must be the generator object for the current frame. `resumeKind`
* must be a `GeneratorResumeKind` stored as an `Int32` value. If it is
* `Next`, continue to the next instruction. If `resumeKind` is `Throw` or
* `Return`, these completions are handled by throwing an exception. See
* `GeneratorThrowOrReturn`.
*
* Category: Functions
* Type: Generators and async functions
* Operands:
* Stack: rval, gen, resumeKind => rval
*/ \
MACRO(CheckResumeKind, check_resume_kind, NULL, 1, 3, 1, JOF_BYTE) \
/*
* Resume execution of a generator, async function, or async generator.
*
* This behaves something like a call instruction. It pushes a stack frame
* (the one saved when `gen` was suspended, rather than a fresh one) and
* runs instructions in it. Once `gen` returns or yields, its return value
* is pushed to this frame's stack and execution continues in this script.
*
* This instruction is emitted only for the `resumeGenerator` self-hosting
* intrinsic. It is used in the implementation of
* `%GeneratorPrototype%.next`, `.throw`, and `.return`.
*
* `gen` must be a suspended generator object. `resumeKind` must be in
* range for `GeneratorResumeKind`.
*
* Category: Functions
* Type: Generators and async functions
* Operands:
* Stack: gen, val, resumeKind => rval
*/ \
MACRO(Resume, resume, NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE) \
/*
* No-op instruction marking the target of a jump instruction.
*
* This instruction and a few others (see `js::BytecodeIsJumpTarget`) are
* jump target instructions. The Baseline Interpreter uses these
* instructions to sync the frame's `interpreterICEntry` after a jump. Ion
* uses them to find block boundaries when translating bytecode to MIR.
*
* Category: Control flow
* Type: Jump targets
* Operands: uint32_t icIndex
* Stack: =>
*/ \
MACRO(JumpTarget, jump_target, NULL, 5, 0, 0, JOF_ICINDEX) \
/*
* Marks the target of the backwards jump for some loop.
*
* This is a jump target instruction (see `JSOp::JumpTarget`). Additionally,
* it checks for interrupts and handles JIT tiering.
*
* The `depthHint` operand is a loop depth hint for Ion. It starts at 1 and
* deeply nested loops all have the same value.
*
* For the convenience of the JITs, scripts must not start with this
* instruction. See bug 1602390.
*
* Category: Control flow
* Type: Jump targets
* Operands: uint32_t icIndex, uint8_t depthHint
* Stack: =>
*/ \
MACRO(LoopHead, loop_head, NULL, 6, 0, 0, JOF_LOOPHEAD) \
/*
* Jump to a 32-bit offset from the current bytecode.
*
* See "Jump instructions" above for details.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t offset
* Stack: =>
*/ \
MACRO(Goto, goto_, NULL, 5, 0, 0, JOF_JUMP) \
/*
* If ToBoolean(`cond`) is false, jumps to a 32-bit offset from the current
* instruction.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t forwardOffset
* Stack: cond =>
*/ \
MACRO(JumpIfFalse, jump_if_false, NULL, 5, 1, 0, JOF_JUMP|JOF_IC) \
/*
* If ToBoolean(`cond`) is true, jump to a 32-bit offset from the current
* instruction.
*
* `offset` may be positive or negative. This is the instruction used at the
* end of a do-while loop to jump back to the top.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t offset
* Stack: cond =>
*/ \
MACRO(JumpIfTrue, jump_if_true, NULL, 5, 1, 0, JOF_JUMP|JOF_IC) \
/*
* Short-circuit for logical AND.
*
* If ToBoolean(`cond`) is false, jump to a 32-bit offset from the current
* instruction. The value remains on the stack.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t forwardOffset
* Stack: cond => cond
*/ \
MACRO(And, and_, NULL, 5, 1, 1, JOF_JUMP|JOF_IC) \
/*
* Short-circuit for logical OR.
*
* If ToBoolean(`cond`) is true, jump to a 32-bit offset from the current
* instruction. The value remains on the stack.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t forwardOffset
* Stack: cond => cond
*/ \
MACRO(Or, or_, NULL, 5, 1, 1, JOF_JUMP|JOF_IC) \
/*
* Short-circuiting for nullish coalescing.
*
* If `val` is not null or undefined, jump to a 32-bit offset from the
* current instruction.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t forwardOffset
* Stack: val => val
*/ \
MACRO(Coalesce, coalesce, NULL, 5, 1, 1, JOF_JUMP) \
/*
* Like `JSOp::JumpIfTrue`, but if the branch is taken, pop and discard an
* additional stack value.
*
* This is used to implement `switch` statements when the
* `JSOp::TableSwitch` optimization is not possible. The switch statement
*
* switch (expr) {
* case A: stmt1;
* case B: stmt2;
* }
*
* compiles to this bytecode:
*
* # dispatch code - evaluate expr, check it against each `case`,
* # jump to the right place in the body or to the end.
* <expr>
* Dup; <A>; StrictEq; Case L1; JumpTarget
* Dup; <B>; StrictEq; Case L2; JumpTarget
* Default LE
*
* # body code
* L1: JumpTarget; <stmt1>
* L2: JumpTarget; <stmt2>
* LE: JumpTarget
*
* This opcode is weird: it's the only one whose ndefs varies depending on
* which way a conditional branch goes. We could implement switch
* statements using `JSOp::JumpIfTrue` and `JSOp::Pop`, but that would also
* be awkward--putting the `JSOp::Pop` inside the `switch` body would
* complicate fallthrough.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t forwardOffset
* Stack: val, cond => val (if !cond)
*/ \
MACRO(Case, case_, NULL, 5, 2, 1, JOF_JUMP) \
/*
* Like `JSOp::Goto`, but pop and discard an additional stack value.
*
* This appears after all cases for a non-optimized `switch` statement. If
* there's a `default:` label, it jumps to that point in the body;
* otherwise it jumps to the next statement.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t forwardOffset
* Stack: lval =>
*/ \
MACRO(Default, default_, NULL, 5, 1, 0, JOF_JUMP) \
/*
* Optimized switch-statement dispatch, used when all `case` labels are
* small integer constants.
*
* If `low <= i <= high`, jump to the instruction at the offset given by
* `script->resumeOffsets()[firstResumeIndex + i - low]`, in bytes from the
* start of the current script's bytecode. Otherwise, jump to the
* instruction at `defaultOffset` from the current instruction. All of
* these offsets must be in range for the current script and must point to
* `JSOp::JumpTarget` instructions.
*
* The following inequalities must hold: `low <= high` and
* `firstResumeIndex + high - low < resumeOffsets().size()`.
*
* Category: Control flow
* Type: Jumps
* Operands: int32_t defaultOffset, int32_t low, int32_t high,
* uint24_t firstResumeIndex
* Stack: i =>
*/ \
MACRO(TableSwitch, table_switch, NULL, 16, 1, 0, JOF_TABLESWITCH) \
/*
* Return `rval`.
*
* This must not be used in derived class constructors. Instead use
* `JSOp::SetRval`, `JSOp::CheckReturn`, and `JSOp::RetRval`.
*
* Category: Control flow
* Type: Return
* Operands:
* Stack: rval =>
*/ \
MACRO(Return, return_, NULL, 1, 1, 0, JOF_BYTE) \
/*
* Push the current stack frame's `returnValue`. If no `JSOp::SetRval`
* instruction has been executed in this stack frame, this is `undefined`.
*
* Every stack frame has a `returnValue` slot, used by top-level scripts,
* generators, async functions, and derived class constructors. Plain
* functions usually use `JSOp::Return` instead.
*
* Category: Control flow
* Type: Return
* Operands:
* Stack: => rval
*/ \
MACRO(GetRval, get_rval, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Store `rval` in the current stack frame's `returnValue` slot.
*
* This instruction must not be used in a toplevel script compiled with the
* `noScriptRval` option.
*
* Category: Control flow
* Type: Return
* Operands:
* Stack: rval =>
*/ \
MACRO(SetRval, set_rval, NULL, 1, 1, 0, JOF_BYTE) \
/*
* Stop execution and return the current stack frame's `returnValue`. If no
* `JSOp::SetRval` instruction has been executed in this stack frame, this
* is `undefined`.
*
* Also emitted at end of every script so consumers don't need to worry
* about running off the end.
*
* If the current script is a derived class constructor, `returnValue` must
* be an object. The script can use `JSOp::CheckReturn` to ensure this.
*
* Category: Control flow
* Type: Return
* Operands:
* Stack: =>
*/ \
MACRO(RetRval, ret_rval, NULL, 1, 0, 0, JOF_BYTE) \
/*
* Check the return value in a derived class constructor.
*
* - If the current stack frame's `returnValue` is an object, push
* `returnValue` onto the stack.
*
* - Otherwise, if the `returnValue` is undefined and `thisval` is an
* object, push `thisval` onto the stack.
*
* - Otherwise, throw a TypeError.
*
* This is exactly what has to happen when a derived class constructor
* returns. `thisval` should be the current value of `this`, or
* `MagicValue(JS_UNINITIALIZED_LEXICAL)` if `this` is uninitialized.
*
* Implements: [The [[Construct]] internal method of JS functions][1],
* steps 13 and 15.
*
* [1]: https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
*
* Category: Control flow
* Type: Return
* Operands:
* Stack: thisval => rval
*/ \
MACRO(CheckReturn, check_return, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Throw `exc`. (ノಠ益ಠ)ノ彡┴──┴
*
* This sets the pending exception to `exc` and jumps to error-handling
* code. If we're in a `try` block, error handling adjusts the stack and
* environment chain and resumes execution at the top of the `catch` or
* `finally` block. Otherwise it starts unwinding the stack.
*
* Implements: [*ThrowStatement* Evaluation][1], step 3.
*
* This is also used in for-of loops. If the body of the loop throws an
* exception, we catch it, close the iterator, then use `JSOp::Throw` to
* rethrow.
*
* [1]: https://tc39.es/ecma262/#sec-throw-statement-runtime-semantics-evaluation
*
* Category: Control flow
* Type: Exceptions
* Operands:
* Stack: exc =>
*/ \
MACRO(Throw, throw_, NULL, 1, 1, 0, JOF_BYTE) \
/*
* Create and throw an Error object.
*
* Sometimes we know at emit time that an operation always throws. For
* example, `delete super.prop;` is allowed in methods, but always throws a
* ReferenceError.
*
* `msgNumber` determines the `.message` and [[Prototype]] of the new Error
* object. It must be an error number in js/public/friend/ErrorNumbers.msg.
* The number of arguments in the error message must be 0.
*
* Category: Control flow
* Type: Exceptions
* Operands: ThrowMsgKind msgNumber
* Stack: =>
*/ \
MACRO(ThrowMsg, throw_msg, NULL, 2, 0, 0, JOF_UINT8) \
/*
* Throws a runtime TypeError for invalid assignment to a `const` binding.
*
* Category: Control flow
* Type: Exceptions
* Operands: uint32_t nameIndex
* Stack:
*/ \
MACRO(ThrowSetConst, throw_set_const, NULL, 5, 0, 0, JOF_ATOM|JOF_NAME) \
/*
* No-op instruction that marks the top of the bytecode for a
* *TryStatement*.
*
* Location information for catch/finally blocks is stored in a side table,
* `script->trynotes()`.
*
* Category: Control flow
* Type: Exceptions
* Operands:
* Stack: =>
*/ \
MACRO(Try, try_, NULL, 1, 0, 0, JOF_BYTE) \
/*
* No-op instruction used by the exception unwinder to determine the
* correct environment to unwind to when performing IteratorClose due to
* destructuring.
*
* This instruction must appear immediately before each
* `JSTRY_DESTRUCTURING` span in a script's try notes.
*
* Category: Control flow
* Type: Exceptions
* Operands:
* Stack: =>
*/ \
MACRO(TryDestructuring, try_destructuring, NULL, 1, 0, 0, JOF_BYTE) \
/*
* Push and clear the pending exception. ┬──┬◡ノ(° -°ノ)
*
* This must be used only in the fixed sequence of instructions following a
* `JSTRY_CATCH` span (see "Bytecode Invariants" above), as that's the only
* way instructions would run with an exception pending.
*
* Used to implement catch-blocks, including the implicit ones generated as
* part of for-of iteration.
*
* Category: Control flow
* Type: Exceptions
* Operands:
* Stack: => exception
*/ \
MACRO(Exception, exception, NULL, 1, 0, 1, JOF_BYTE) \
/*
* No-op instruction that marks the start of a `finally` block.
*
* Category: Control flow
* Type: Exceptions
* Operands:
* Stack: =>
*/ \
MACRO(Finally, finally, NULL, 1, 0, 0, JOF_BYTE) \
/*
* Push `MagicValue(JS_UNINITIALIZED_LEXICAL)`, a magic value used to mark
* a binding as uninitialized.
*
* This magic value must be used only by `JSOp::InitLexical`.
*
* Category: Variables and scopes
* Type: Initialization
* Operands:
* Stack: => uninitialized
*/ \
MACRO(Uninitialized, uninitialized, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Initialize an optimized local lexical binding; or mark it as
* uninitialized.
*
* This stores the value `v` in the fixed slot `localno` in the current
* stack frame. If `v` is the magic value produced by `JSOp::Uninitialized`,
* this marks the binding as uninitialized. Otherwise this initializes the
* binding with value `v`.
*
* Implements: [CreateMutableBinding][1] step 3, substep "record that it is
* uninitialized", and [InitializeBinding][2], for optimized locals. (Note:
* this is how `const` bindings are initialized.)
*
* [1]: https://tc39.es/ecma262/#sec-declarative-environment-records-createmutablebinding-n-d
* [2]: https://tc39.es/ecma262/#sec-declarative-environment-records-initializebinding-n-v
*
* Category: Variables and scopes
* Type: Initialization
* Operands: uint24_t localno
* Stack: v => v
*/ \
MACRO(InitLexical, init_lexical, NULL, 4, 1, 1, JOF_LOCAL|JOF_NAME) \
/*
* Initialize a global lexical binding.
*
* The binding must already have been created by
* `GlobalOrEvalDeclInstantiation` and must be uninitialized.
*
* Like `JSOp::InitLexical` but for global lexicals. Unlike `InitLexical`
* this can't be used to mark a binding as uninitialized.
*
* Category: Variables and scopes
* Type: Initialization
* Operands: uint32_t nameIndex
* Stack: val => val
*/ \
MACRO(InitGLexical, init_g_lexical, NULL, 5, 1, 1, JOF_ATOM|JOF_NAME|JOF_PROPINIT|JOF_GNAME|JOF_IC) \
/*
* Initialize an aliased lexical binding; or mark it as uninitialized.
*
* Like `JSOp::InitLexical` but for aliased bindings.
*
* Note: There is no even-less-optimized `InitName` instruction because JS
* doesn't need it. We always know statically which binding we're
* initializing.
*
* `hops` is usually 0, but in `function f(a=eval("var b;")) { }`, the
* argument `a` is initialized from inside a nested scope, so `hops == 1`.
*
* Category: Variables and scopes
* Type: Initialization
* Operands: uint8_t hops, uint24_t slot
* Stack: v => v
*/ \
MACRO(InitAliasedLexical, init_aliased_lexical, NULL, 5, 1, 1, JOF_ENVCOORD|JOF_NAME|JOF_PROPINIT) \
/*
* Throw a ReferenceError if the value on top of the stack is uninitialized.
*
* Typically used after `JSOp::GetLocal` with the same `localno`.
*
* Implements: [GetBindingValue][1] step 3 and [SetMutableBinding][2] step
* 4 for declarative Environment Records.
*
* [1]: https://tc39.es/ecma262/#sec-declarative-environment-records-getbindingvalue-n-s
* [2]: https://tc39.es/ecma262/#sec-declarative-environment-records-setmutablebinding-n-v-s
*
* Category: Variables and scopes
* Type: Initialization
* Operands: uint24_t localno
* Stack: v => v
*/ \
MACRO(CheckLexical, check_lexical, NULL, 4, 1, 1, JOF_LOCAL|JOF_NAME) \
/*
* Like `JSOp::CheckLexical` but for aliased bindings.
*
* Typically used after `JSOp::GetAliasedVar` with the same hops/slot.
*
* Note: There are no `CheckName` or `CheckGName` instructions because
* they're unnecessary. `JSOp::{Get,Set}{Name,GName}` all check for
* uninitialized lexicals and throw if needed.
*
* Category: Variables and scopes
* Type: Initialization
* Operands: uint8_t hops, uint24_t slot
* Stack: v => v
*/ \
MACRO(CheckAliasedLexical, check_aliased_lexical, NULL, 5, 1, 1, JOF_ENVCOORD|JOF_NAME) \
/*
* Throw a ReferenceError if the value on top of the stack is
* `MagicValue(JS_UNINITIALIZED_LEXICAL)`. Used in derived class
* constructors to check `this` (which needs to be initialized before use,
* by calling `super()`).
*
* Implements: [GetThisBinding][1] step 3.
*
* [1]: https://tc39.es/ecma262/#sec-function-environment-records-getthisbinding
*
* Category: Variables and scopes
* Type: Initialization
* Operands:
* Stack: this => this
*/ \
MACRO(CheckThis, check_this, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Look up a name on the global lexical environment's chain and push the
* environment which contains a binding for that name. If no such binding
* exists, push the global lexical environment.
*
* Category: Variables and scopes
* Type: Looking up bindings
* Operands: uint32_t nameIndex
* Stack: => global
*/ \
MACRO(BindGName, bind_g_name, NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_GNAME|JOF_IC) \
/*
* Look up a name on the environment chain and push the environment which
* contains a binding for that name. If no such binding exists, push the
* global lexical environment.
*
* Category: Variables and scopes
* Type: Looking up bindings
* Operands: uint32_t nameIndex
* Stack: => env
*/ \
MACRO(BindName, bind_name, NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_IC) \
/*
* Find a binding on the environment chain and push its value.
*
* If the binding is an uninitialized lexical, throw a ReferenceError. If
* no such binding exists, throw a ReferenceError unless the next
* instruction is `JSOp::Typeof`, in which case push `undefined`.
*
* Implements: [ResolveBinding][1] followed by [GetValue][2]
* (adjusted hackily for `typeof`).
*
* This is the fallback `Get` instruction that handles all unoptimized
* cases. Optimized instructions follow.
*
* [1]: https://tc39.es/ecma262/#sec-resolvebinding
* [2]: https://tc39.es/ecma262/#sec-getvalue
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint32_t nameIndex
* Stack: => val
*/ \
MACRO(GetName, get_name, NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_IC) \
/*
* Find a global binding and push its value.
*
* This searches the global lexical environment and, failing that, the
* global object. (Unlike most declarative environments, the global lexical
* environment can gain more bindings after compilation, possibly shadowing
* global object properties.)
*
* This is an optimized version of `JSOp::GetName` that skips all local
* scopes, for use when the name doesn't refer to any local binding.
* `NonSyntacticVariablesObject`s break this optimization, so if the
* current script has a non-syntactic global scope, use `JSOp::GetName`
* instead.
*
* Like `JSOp::GetName`, this throws a ReferenceError if no such binding is
* found (unless the next instruction is `JSOp::Typeof`) or if the binding
* is an uninitialized lexical.
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint32_t nameIndex
* Stack: => val
*/ \
MACRO(GetGName, get_g_name, NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_GNAME|JOF_IC) \
/*
* Push the value of an argument that is stored in the stack frame
* or in an `ArgumentsObject`.
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint16_t argno
* Stack: => arguments[argno]
*/ \
MACRO(GetArg, get_arg, NULL, 3, 0, 1, JOF_QARG|JOF_NAME) \
/*
* Push the value of an optimized local variable.
*
* If the variable is an uninitialized lexical, push
* `MagicValue(JS_UNINIITALIZED_LEXICAL)`.
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint24_t localno
* Stack: => val
*/ \
MACRO(GetLocal, get_local, NULL, 4, 0, 1, JOF_LOCAL|JOF_NAME) \
/*
* Push the value of an aliased binding.
*
* Local bindings that aren't closed over or dynamically accessed are
* stored in stack slots. Global and `with` bindings are object properties.
* All other bindings are called "aliased" and stored in
* `EnvironmentObject`s.
*
* Where possible, `Aliased` instructions are used to access aliased
* bindings. (There's no difference in meaning between `AliasedVar` and
* `AliasedLexical`.) Each of these instructions has operands `hops` and
* `slot` that encode an [`EnvironmentCoordinate`][1], directions to the
* binding from the current environment object.
*
* `Aliased` instructions can't be used when there's a dynamic scope (due
* to non-strict `eval` or `with`) that might shadow the aliased binding.
*
* [1]: https://searchfox.org/mozilla-central/search?q=symbol:T_js%3A%3AEnvironmentCoordinate
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint8_t hops, uint24_t slot
* Stack: => aliasedVar
*/ \
MACRO(GetAliasedVar, get_aliased_var, NULL, 5, 0, 1, JOF_ENVCOORD|JOF_NAME) \
/*
* Push the value of an aliased binding, which may have to bypass a DebugEnvironmentProxy
* on the environment chain.
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint8_t hops, uint24_t slot
* Stack: => aliasedVar
*/ \
MACRO(GetAliasedDebugVar, get_aliased_debug_var, NULL, 5, 0, 1, JOF_DEBUGCOORD|JOF_NAME) \
/*
* Get the value of a module import by name and pushes it onto the stack.
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint32_t nameIndex
* Stack: => val
*/ \
MACRO(GetImport, get_import, NULL, 5, 0, 1, JOF_ATOM|JOF_NAME) \
/*
* Get the value of a binding from the environment `env`. If the name is
* not bound in `env`, throw a ReferenceError.
*
* `env` must be an environment currently on the environment chain, pushed
* by `JSOp::BindName` or `JSOp::BindVar`.
*
* Note: `JSOp::BindName` and `JSOp::GetBoundName` are the two halves of the
* `JSOp::GetName` operation: finding and reading a variable. This
* decomposed version is needed to implement the compound assignment and
* increment/decrement operators, which get and then set a variable. The
* spec says the variable lookup is done only once. If we did the lookup
* twice, there would be observable bugs, thanks to dynamic scoping. We
* could set the wrong variable or call proxy traps incorrectly.
*
* Implements: [GetValue][1] steps 4 and 6.
*
* [1]: https://tc39.es/ecma262/#sec-getvalue
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint32_t nameIndex
* Stack: env => v
*/ \
MACRO(GetBoundName, get_bound_name, NULL, 5, 1, 1, JOF_ATOM|JOF_NAME|JOF_IC) \
/*
* Push the value of an intrinsic onto the stack.
*
* Non-standard. Intrinsics are slots in the intrinsics holder object (see
* `GlobalObject::getIntrinsicsHolder`), which is used in lieu of global
* bindings in self-hosting code.
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint32_t nameIndex
* Stack: => intrinsic[name]
*/ \
MACRO(GetIntrinsic, get_intrinsic, NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_IC) \
/*
* Pushes the currently executing function onto the stack.
*
* The current script must be a function script.
*
* Used to implement `super`. This is also used sometimes as a minor
* optimization when a named function expression refers to itself by name:
*
* f = function fac(n) { ... fac(n - 1) ... };
*
* This lets us optimize away a lexical environment that contains only the
* binding for `fac`, unless it's otherwise observable (via `with`, `eval`,
* or a nested closure).
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands:
* Stack: => callee
*/ \
MACRO(Callee, callee, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Load the callee stored in a CallObject on the environment chain. The
* `numHops` operand is the number of environment objects to skip on the
* environment chain. The environment chain element indicated by `numHops`
* must be a CallObject.
*
* Category: Variables and scopes
* Type: Getting binding values
* Operands: uint8_t numHops
* Stack: => callee
*/ \
MACRO(EnvCallee, env_callee, NULL, 2, 0, 1, JOF_UINT8) \
/*
* Assign `val` to the binding in `env` with the name given by `nameIndex`.
* Throw a ReferenceError if the binding is an uninitialized lexical.
* This can call setters and/or proxy traps.
*
* `env` must be an environment currently on the environment chain,
* pushed by `JSOp::BindName` or `JSOp::BindVar`.
*
* This is the fallback `Set` instruction that handles all unoptimized
* cases. Optimized instructions follow.
*
* Implements: [PutValue][1] steps 5 and 7 for unoptimized bindings.
*
* Note: `JSOp::BindName` and `JSOp::SetName` are the two halves of simple
* assignment: finding and setting a variable. They are two separate
* instructions because, per spec, the "finding" part happens before
* evaluating the right-hand side of the assignment, and the "setting" part
* after. Optimized cases don't need a `Bind` instruction because the
* "finding" is done statically.
*
* [1]: https://tc39.es/ecma262/#sec-putvalue
*
* Category: Variables and scopes
* Type: Setting binding values
* Operands: uint32_t nameIndex
* Stack: env, val => val
*/ \
MACRO(SetName, set_name, NULL, 5, 2, 1, JOF_ATOM|JOF_NAME|JOF_PROPSET|JOF_CHECKSLOPPY|JOF_IC) \
/*
* Like `JSOp::SetName`, but throw a TypeError if there is no binding for
* the specified name in `env`, or if the binding is immutable (a `const`
* or read-only property).
*
* Implements: [PutValue][1] steps 5 and 7 for strict mode code.
*
* [1]: https://tc39.es/ecma262/#sec-putvalue
*
* Category: Variables and scopes
* Type: Setting binding values
* Operands: uint32_t nameIndex
* Stack: env, val => val
*/ \
MACRO(StrictSetName, strict_set_name, NULL, 5, 2, 1, JOF_ATOM|JOF_NAME|JOF_PROPSET|JOF_CHECKSTRICT|JOF_IC) \
/*
* Like `JSOp::SetName`, but for assigning to globals. `env` must be an
* environment pushed by `JSOp::BindGName`.
*
* Category: Variables and scopes
* Type: Setting binding values
* Operands: uint32_t nameIndex
* Stack: env, val => val
*/ \
MACRO(SetGName, set_g_name, NULL, 5, 2, 1, JOF_ATOM|JOF_NAME|JOF_PROPSET|JOF_GNAME|JOF_CHECKSLOPPY|JOF_IC) \
/*
* Like `JSOp::StrictSetGName`, but for assigning to globals. `env` must be
* an environment pushed by `JSOp::BindGName`.
*
* Category: Variables and scopes
* Type: Setting binding values
* Operands: uint32_t nameIndex
* Stack: env, val => val
*/ \
MACRO(StrictSetGName, strict_set_g_name, NULL, 5, 2, 1, JOF_ATOM|JOF_NAME|JOF_PROPSET|JOF_GNAME|JOF_CHECKSTRICT|JOF_IC) \
/*
* Assign `val` to an argument binding that's stored in the stack frame or
* in an `ArgumentsObject`.
*
* Category: Variables and scopes
* Type: Setting binding values
* Operands: uint16_t argno
* Stack: val => val
*/ \
MACRO(SetArg, set_arg, NULL, 3, 1, 1, JOF_QARG|JOF_NAME) \
/*
* Assign to an optimized local binding.
*
* Category: Variables and scopes
* Type: Setting binding values
* Operands: uint24_t localno
* Stack: v => v
*/ \
MACRO(SetLocal, set_local, NULL, 4, 1, 1, JOF_LOCAL|JOF_NAME) \
/*
* Assign to an aliased binding.
*
* Implements: [SetMutableBinding for declarative Environment Records][1],
* in certain cases where it's known that the binding exists, is mutable,
* and has been initialized.
*
* [1]: https://tc39.es/ecma262/#sec-declarative-environment-records-setmutablebinding-n-v-s
*
* Category: Variables and scopes
* Type: Setting binding values
* Operands: uint8_t hops, uint24_t slot
* Stack: val => val
*/ \
MACRO(SetAliasedVar, set_aliased_var, NULL, 5, 1, 1, JOF_ENVCOORD|JOF_NAME|JOF_PROPSET) \
/*
* Assign to an intrinsic.
*
* Nonstandard. Intrinsics are used in lieu of global bindings in self-
* hosted code. The value is actually stored in the intrinsics holder
* object, `GlobalObject::getIntrinsicsHolder`. (Self-hosted code doesn't
* have many global `var`s, but it has many `function`s.)
*
* Category: Variables and scopes
* Type: Setting binding values
* Operands: uint32_t nameIndex
* Stack: val => val
*/ \
MACRO(SetIntrinsic, set_intrinsic, NULL, 5, 1, 1, JOF_ATOM|JOF_NAME) \
/*
* Push a lexical environment onto the environment chain.
*
* The `LexicalScope` indicated by `lexicalScopeIndex` determines the shape
* of the new `BlockLexicalEnvironmentObject`. All bindings in the new
* environment are marked as uninitialized.
*
* Implements: [Evaluation of *Block*][1], steps 1-4.
*
* #### Fine print for environment chain instructions
*
* The following rules for `JSOp::{Push,Pop}LexicalEnv` also apply to
* `JSOp::PushClassBodyEnv`, `JSOp::PushVarEnv`, and
* `JSOp::{Enter,Leave}With`.
*
* Each `JSOp::PopLexicalEnv` instruction matches a particular
* `JSOp::PushLexicalEnv` instruction in the same script and must have the
* same scope and stack depth as the instruction immediately after that
* `PushLexicalEnv`.
*
* `JSOp::PushLexicalEnv` enters a scope that extends to some set of
* instructions in the script. Code must not jump into or out of this
* region: control can enter only by executing `PushLexicalEnv` and can
* exit only by executing a `PopLexicalEnv` or by exception unwinding. (A
* `JSOp::PopLexicalEnv` is always emitted at the end of the block, and
* extra copies are emitted on "exit slides", where a `break`, `continue`,
* or `return` statement exits the scope.)
*
* The script's `JSScript::scopeNotes()` must identify exactly which
* instructions begin executing in this scope. Typically this means a
* single entry marking the contiguous chunk of bytecode from the
* instruction after `JSOp::PushLexicalEnv` to `JSOp::PopLexicalEnv`
* (inclusive); but if that range contains any instructions on exit slides,
* after a `JSOp::PopLexicalEnv`, then those must be correctly noted as
* *outside* the scope.
*
* [1]: https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands: uint32_t lexicalScopeIndex
* Stack: =>
*/ \
MACRO(PushLexicalEnv, push_lexical_env, NULL, 5, 0, 0, JOF_SCOPE) \
/*
* Pop a lexical or class-body environment from the environment chain.
*
* See `JSOp::PushLexicalEnv` for the fine print.
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands:
* Stack: =>
*/ \
MACRO(PopLexicalEnv, pop_lexical_env, NULL, 1, 0, 0, JOF_BYTE) \
/*
* No-op instruction that indicates leaving an optimized lexical scope.
*
* If all bindings in a lexical scope are optimized into stack slots, then
* the runtime environment objects for that scope are optimized away. No
* `JSOp::{Push,Pop}LexicalEnv` instructions are emitted. However, the
* debugger still needs to be notified when control exits a scope; that's
* what this instruction does.
*
* The last instruction in a lexical or class-body scope, as indicated by
* scope notes, must be either this instruction (if the scope is optimized)
* or `JSOp::PopLexicalEnv` (if not).
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands:
* Stack: =>
*/ \
MACRO(DebugLeaveLexicalEnv, debug_leave_lexical_env, NULL, 1, 0, 0, JOF_BYTE) \
/*
* Replace the current block on the environment chain with a fresh block
* with uninitialized bindings. This implements the behavior of inducing a
* fresh lexical environment for every iteration of a for-in/of loop whose
* loop-head declares lexical variables that may be captured.
*
* The current environment must be a BlockLexicalEnvironmentObject.
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands:
* Stack: =>
*/ \
MACRO(RecreateLexicalEnv, recreate_lexical_env, NULL, 1, 0, 0, JOF_BYTE) \
/*
* Like `JSOp::RecreateLexicalEnv`, but the values of all the bindings are
* copied from the old block to the new one. This is used for C-style
* `for(let ...; ...; ...)` loops.
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands:
* Stack: =>
*/ \
MACRO(FreshenLexicalEnv, freshen_lexical_env, NULL, 1, 0, 0, JOF_BYTE) \
/*
* Push a ClassBody environment onto the environment chain.
*
* Like `JSOp::PushLexicalEnv`, but pushes a `ClassBodyEnvironmentObject`
* rather than a `BlockLexicalEnvironmentObject`. `JSOp::PopLexicalEnv` is
* used to pop class-body environments as well as lexical environments.
*
* See `JSOp::PushLexicalEnv` for the fine print.
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands: uint32_t lexicalScopeIndex
* Stack: =>
*/ \
MACRO(PushClassBodyEnv, push_class_body_env, NULL, 5, 0, 0, JOF_SCOPE) \
/*
* Push a var environment onto the environment chain.
*
* Like `JSOp::PushLexicalEnv`, but pushes a `VarEnvironmentObject` rather
* than a `BlockLexicalEnvironmentObject`. The difference is that
* non-strict direct `eval` can add bindings to a var environment; see
* `VarScope` in Scope.h.
*
* See `JSOp::PushLexicalEnv` for the fine print.
*
* There is no corresponding `JSOp::PopVarEnv` operation, because a
* `VarEnvironmentObject` is never popped from the environment chain.
*
* Implements: Places in the spec where the VariableEnvironment is set:
*
* - The bit in [PerformEval][1] where, in strict direct eval, the new
* eval scope is taken as *varEnv* and becomes "*runningContext*'s
* VariableEnvironment".
*
* - The weird scoping rules for functions with default parameter
* expressions, as specified in [FunctionDeclarationInstantiation][2]
* step 28 ("NOTE: A separate Environment Record is needed...").
*
* Note: The spec also pushes a new VariableEnvironment on entry to every
* function, but the VM takes care of that as part of pushing the stack
* frame, before the function script starts to run, so `JSOp::PushVarEnv` is
* not needed.
*
* [1]: https://tc39.es/ecma262/#sec-performeval
* [2]: https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands: uint32_t scopeIndex
* Stack: =>
*/ \
MACRO(PushVarEnv, push_var_env, NULL, 5, 0, 0, JOF_SCOPE) \
/*
* Push a `WithEnvironmentObject` wrapping ToObject(`val`) to the
* environment chain.
*
* Implements: [Evaluation of `with` statements][1], steps 2-6.
*
* Operations that may need to consult a WithEnvironment can't be correctly
* implemented using optimized instructions like `JSOp::GetLocal`. A script
* must use the deoptimized `JSOp::GetName`, `BindName`, `SetName`, and
* `DelName` instead. Since those instructions don't work correctly with
* optimized locals and arguments, all bindings in scopes enclosing a
* `with` statement are marked as "aliased" and deoptimized too.
*
* See `JSOp::PushLexicalEnv` for the fine print.
*
* [1]: https://tc39.es/ecma262/#sec-with-statement-runtime-semantics-evaluation
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands: uint32_t staticWithIndex
* Stack: val =>
*/ \
MACRO(EnterWith, enter_with, NULL, 5, 1, 0, JOF_SCOPE) \
/*
* Pop a `WithEnvironmentObject` from the environment chain.
*
* See `JSOp::PushLexicalEnv` for the fine print.
*
* Implements: [Evaluation of `with` statements][1], step 8.
*
* [1]: https://tc39.es/ecma262/#sec-with-statement-runtime-semantics-evaluation
*
* Category: Variables and scopes
* Type: Entering and leaving environments
* Operands:
* Stack: =>
*/ \
MACRO(LeaveWith, leave_with, NULL, 1, 0, 0, JOF_BYTE) \
/*
* Push the current VariableEnvironment (the environment on the environment
* chain designated to receive new variables).
*
* Implements: [Annex B.3.3.1, changes to FunctionDeclarationInstantiation
* for block-level functions][1], step 1.a.ii.3.a, and similar steps in
* other Annex B.3.3 algorithms, when setting the function's second binding
* can't be optimized.
*
* [1]: https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
*
* Category: Variables and scopes
* Type: Creating and deleting bindings
* Operands:
* Stack: => env
*/ \
MACRO(BindVar, bind_var, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Check for conflicting bindings and then initialize them in global or
* sloppy eval scripts. This is required for global scripts with any
* top-level bindings, or any sloppy-eval scripts with any non-lexical
* top-level bindings.
*
* Implements: [GlobalDeclarationInstantiation][1] and
* [EvalDeclarationInstantiation][2] (except step 12).
*
* The `lastFun` argument is a GCThingIndex of the last hoisted top-level
* function that is part of top-level script initialization. The gcthings
* from index `0` thru `lastFun` contain only scopes and hoisted functions.
*
* [1]: https://tc39.es/ecma262/#sec-globaldeclarationinstantiation
* [2]: https://tc39.es/ecma262/#sec-evaldeclarationinstantiation
*
* Category: Variables and scopes
* Type: Creating and deleting bindings
* Operands: uint32_t lastFun
* Stack: =>
*/ \
MACRO(GlobalOrEvalDeclInstantiation, global_or_eval_decl_instantiation, NULL, 5, 0, 0, JOF_GCTHING) \
/*
* Look up a variable on the environment chain and delete it. Push `true`
* on success (if a binding was deleted, or if no such binding existed in
* the first place), `false` otherwise (most kinds of bindings can't be
* deleted).
*
* Implements: [`delete` *Identifier*][1], which [is a SyntaxError][2] in
* strict mode code.
*
* [1]: https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
* [2]: https://tc39.es/ecma262/#sec-delete-operator-static-semantics-early-errors
*
* Category: Variables and scopes
* Type: Creating and deleting bindings
* Operands: uint32_t nameIndex
* Stack: => succeeded
*/ \
MACRO(DelName, del_name, NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_CHECKSLOPPY) \
/*
* Create and push the `arguments` object for the current function activation.
*
* When it exists, `arguments` is stored in an ordinary local variable.
* `JSOp::Arguments` is used in function preludes, to populate that variable
* before the function body runs, *not* each time `arguments` appears in a
* function.
*
* If a function clearly doesn't use `arguments`, we optimize it away when
* emitting bytecode. The function's script won't use `JSOp::Arguments` at
* all.
*
* The current script must be a function script. This instruction must
* execute at most once per function activation.
*
* Category: Variables and scopes
* Type: Function environment setup
* Operands:
* Stack: => arguments
*/ \
MACRO(Arguments, arguments, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Create and push the rest parameter array for current function call.
*
* This must appear only in a script for a function that has a rest
* parameter.
*
* Category: Variables and scopes
* Type: Function environment setup
* Operands:
* Stack: => rest
*/ \
MACRO(Rest, rest, NULL, 1, 0, 1, JOF_BYTE|JOF_IC) \
/*
* Determines the `this` value for current function frame and pushes it
* onto the stack.
*
* In functions, `this` is stored in a local variable. This instruction is
* used in the function prologue to get the value to initialize that
* variable. (This doesn't apply to arrow functions, becauses they don't
* have a `this` binding; also, `this` is optimized away if it's unused.)
*
* Functions that have a `this` binding have a local variable named
* `".this"`, which is initialized using this instruction in the function
* prologue.
*
* In non-strict functions, `this` is always an object. Undefined/null
* `this` is converted into the global `this` value. Other primitive values
* are boxed. See `js::BoxNonStrictThis`.
*
* Category: Variables and scopes
* Type: Function environment setup
* Operands:
* Stack: => this
*/ \
MACRO(FunctionThis, function_this, NULL, 1, 0, 1, JOF_BYTE) \
/*
* Pop the top value from the stack and discard it.
*
* Category: Stack operations
* Operands:
* Stack: v =>
*/ \
MACRO(Pop, pop, NULL, 1, 1, 0, JOF_BYTE) \
/*
* Pop the top `n` values from the stack. `n` must be <= the current stack
* depth.
*
* Category: Stack operations
* Operands: uint16_t n
* Stack: v[n-1], ..., v[1], v[0] =>
*/ \
MACRO(PopN, pop_n, NULL, 3, -1, 0, JOF_UINT16) \
/*
* Push a copy of the top value on the stack.
*
* Category: Stack operations
* Operands:
* Stack: v => v, v
*/ \
MACRO(Dup, dup, NULL, 1, 1, 2, JOF_BYTE) \
/*
* Duplicate the top two values on the stack.
*
* Category: Stack operations
* Operands:
* Stack: v1, v2 => v1, v2, v1, v2
*/ \
MACRO(Dup2, dup2, NULL, 1, 2, 4, JOF_BYTE) \
/*
* Push a copy of the nth value from the top of the stack.
*
* `n` must be less than the current stack depth.
*
* Category: Stack operations
* Operands: uint24_t n
* Stack: v[n], v[n-1], ..., v[1], v[0] =>
* v[n], v[n-1], ..., v[1], v[0], v[n]
*/ \
MACRO(DupAt, dup_at, NULL, 4, 0, 1, JOF_UINT24) \
/*
* Swap the top two values on the stack.
*
* Category: Stack operations
* Operands:
* Stack: v1, v2 => v2, v1
*/ \
MACRO(Swap, swap, NULL, 1, 2, 2, JOF_BYTE) \
/*
* Pick the nth element from the stack and move it to the top of the stack.
*
* Category: Stack operations
* Operands: uint8_t n
* Stack: v[n], v[n-1], ..., v[1], v[0] => v[n-1], ..., v[1], v[0], v[n]
*/ \
MACRO(Pick, pick, NULL, 2, 0, 0, JOF_UINT8) \
/*
* Move the top of the stack value under the `n`th element of the stack.
* `n` must not be 0.
*
* Category: Stack operations
* Operands: uint8_t n
* Stack: v[n], v[n-1], ..., v[1], v[0] => v[0], v[n], v[n-1], ..., v[1]
*/ \
MACRO(Unpick, unpick, NULL, 2, 0, 0, JOF_UINT8) \
/*
* Do nothing. This is used when we need distinct bytecode locations for
* various mechanisms.
*
* Category: Other
* Operands:
* Stack: =>
*/ \
MACRO(Nop, nop, NULL, 1, 0, 0, JOF_BYTE) \
/*
* No-op instruction emitted immediately after `JSOp::*Eval` so that direct
* eval does not have to do slow pc-to-line mapping.
*
* The `lineno` operand should agree with this script's source notes about
* the line number of the preceding `*Eval` instruction.
*
* Category: Other
* Operands: uint32_t lineno
* Stack: =>
*/ \
MACRO(Lineno, lineno, NULL, 5, 0, 0, JOF_UINT32) \
/*
* No-op instruction to hint that the top stack value is uninteresting.
*
* This affects only debug output and some error messages.
* In array destructuring, we emit bytecode that is roughly equivalent to
* `result.done ? undefined : result.value`.
* `NopDestructuring` is emitted after the `undefined`, so that the
* expression decompiler and disassembler know to casually ignore the
* possibility of `undefined`, and render the result of the conditional
* expression simply as "`result.value`".
*
* Category: Other
* Operands:
* Stack: =>
*/ \
MACRO(NopDestructuring, nop_destructuring, NULL, 1, 0, 0, JOF_BYTE) \
/*
* No-op instruction only emitted in some self-hosted functions. Not
* handled by the JITs or Baseline Interpreter so the script always runs in
* the C++ interpreter.
*
* Category: Other
* Operands:
* Stack: =>
*/ \
MACRO(ForceInterpreter, force_interpreter, NULL, 1, 0, 0, JOF_BYTE) \
/*
* Examine the top stack value, asserting that it's either a self-hosted
* function or a self-hosted intrinsic. This does nothing in a non-debug
* build.
*
* Category: Other
* Operands:
* Stack: checkVal => checkVal
*/ \
MACRO(DebugCheckSelfHosted, debug_check_self_hosted, NULL, 1, 1, 1, JOF_BYTE) \
/*
* Break in the debugger, if one is attached. Otherwise this is a no-op.
*
* The [`Debugger` API][1] offers a way to hook into this instruction.
*
* Implements: [Evaluation for *DebuggerStatement*][2].
*
* [1]: https://developer.mozilla.org/en-US/docs/Tools/Debugger-API/Debugger
* [2]: https://tc39.es/ecma262/#sec-debugger-statement-runtime-semantics-evaluation
*
* Category: Other
* Operands:
* Stack: =>
*/ \
MACRO(Debugger, debugger, NULL, 1, 0, 0, JOF_BYTE)
// clang-format on
/*
* In certain circumstances it may be useful to "pad out" the opcode space to
* a power of two. Use this macro to do so.
*/
#define FOR_EACH_TRAILING_UNUSED_OPCODE(MACRO) \
IF_RECORD_TUPLE(/* empty */, MACRO(227)) \
IF_RECORD_TUPLE(/* empty */, MACRO(228)) \
IF_RECORD_TUPLE(/* empty */, MACRO(229)) \
IF_RECORD_TUPLE(/* empty */, MACRO(230)) \
IF_RECORD_TUPLE(/* empty */, MACRO(231)) \
IF_RECORD_TUPLE(/* empty */, MACRO(232)) \
IF_RECORD_TUPLE(/* empty */, MACRO(233)) \
MACRO(234) \
MACRO(235) \
MACRO(236) \
MACRO(237) \
MACRO(238) \
MACRO(239) \
MACRO(240) \
MACRO(241) \
MACRO(242) \
MACRO(243) \
MACRO(244) \
MACRO(245) \
MACRO(246) \
MACRO(247) \
MACRO(248) \
MACRO(249) \
MACRO(250) \
MACRO(251) \
MACRO(252) \
MACRO(253) \
MACRO(254) \
MACRO(255)
namespace js {
// Sanity check that opcode values and trailing unused opcodes completely cover
// the [0, 256) range. Avert your eyes! You don't want to know how the
// sausage gets made.
// clang-format off
#define PLUS_ONE(...) \
+ 1
constexpr int JSOP_LIMIT = 0 FOR_EACH_OPCODE(PLUS_ONE);
#undef PLUS_ONE
#define TRAILING_VALUE_AND_VALUE_PLUS_ONE(val) \
val) && (val + 1 ==
static_assert((JSOP_LIMIT ==
FOR_EACH_TRAILING_UNUSED_OPCODE(TRAILING_VALUE_AND_VALUE_PLUS_ONE)
256),
"trailing unused opcode values monotonically increase "
"from JSOP_LIMIT to 255");
#undef TRAILING_VALUE_AND_VALUE_PLUS_ONE
// clang-format on
// Define JSOpLength_* constants for all ops.
#define DEFINE_LENGTH_CONSTANT(op, op_snake, image, len, ...) \
constexpr size_t JSOpLength_##op = len;
FOR_EACH_OPCODE(DEFINE_LENGTH_CONSTANT)
#undef DEFINE_LENGTH_CONSTANT
} // namespace js
/*
* JS operation bytecodes.
*/
enum class JSOp : uint8_t {
#define ENUMERATE_OPCODE(op, ...) op,
FOR_EACH_OPCODE(ENUMERATE_OPCODE)
#undef ENUMERATE_OPCODE
};
#endif // vm_Opcodes_h
|