mirror of
https://github.com/ruby/ruby.git
synced 2026-01-27 04:24:23 +00:00
ZJIT: Implement expandarray (#14847)
Only support the simple case: no splat or rest.
lobsters before:
<details>
```
***ZJIT: Printing ZJIT statistics on exit***
Top-20 not inlined C methods (60.5% of total 11,039,954):
Kernel#is_a?: 1,030,769 ( 9.3%)
String#<<: 851,954 ( 7.7%)
Hash#[]=: 742,941 ( 6.7%)
Regexp#match?: 399,894 ( 3.6%)
String#empty?: 353,775 ( 3.2%)
Hash#key?: 349,147 ( 3.2%)
String#start_with?: 334,961 ( 3.0%)
Kernel#respond_to?: 316,528 ( 2.9%)
ObjectSpace::WeakKeyMap#[]: 238,978 ( 2.2%)
TrueClass#===: 235,771 ( 2.1%)
FalseClass#===: 231,144 ( 2.1%)
Array#include?: 211,385 ( 1.9%)
Hash#fetch: 204,702 ( 1.9%)
Kernel#block_given?: 181,797 ( 1.6%)
Kernel#dup: 179,341 ( 1.6%)
BasicObject#!=: 175,997 ( 1.6%)
Class#new: 168,079 ( 1.5%)
Kernel#kind_of?: 165,600 ( 1.5%)
String#==: 157,735 ( 1.4%)
Module#clock_gettime: 144,992 ( 1.3%)
Top-20 not annotated C methods (61.4% of total 11,202,087):
Kernel#is_a?: 1,212,660 (10.8%)
String#<<: 851,954 ( 7.6%)
Hash#[]=: 743,120 ( 6.6%)
Regexp#match?: 399,894 ( 3.6%)
String#empty?: 361,013 ( 3.2%)
Hash#key?: 349,147 ( 3.1%)
String#start_with?: 334,961 ( 3.0%)
Kernel#respond_to?: 316,528 ( 2.8%)
ObjectSpace::WeakKeyMap#[]: 238,978 ( 2.1%)
TrueClass#===: 235,771 ( 2.1%)
FalseClass#===: 231,144 ( 2.1%)
Array#include?: 211,385 ( 1.9%)
Hash#fetch: 204,702 ( 1.8%)
Kernel#block_given?: 191,666 ( 1.7%)
Kernel#dup: 179,348 ( 1.6%)
BasicObject#!=: 176,181 ( 1.6%)
Class#new: 168,079 ( 1.5%)
Kernel#kind_of?: 165,634 ( 1.5%)
String#==: 163,667 ( 1.5%)
Module#clock_gettime: 144,992 ( 1.3%)
Top-2 not optimized method types for send (100.0% of total 72,318):
cfunc: 48,055 (66.4%)
iseq: 24,263 (33.6%)
Top-6 not optimized method types for send_without_block (100.0% of total 4,523,682):
iseq: 2,271,936 (50.2%)
bmethod: 985,636 (21.8%)
optimized: 949,703 (21.0%)
alias: 310,747 ( 6.9%)
null: 5,106 ( 0.1%)
cfunc: 554 ( 0.0%)
Top-13 not optimized instructions (100.0% of total 4,293,171):
invokesuper: 2,373,404 (55.3%)
invokeblock: 811,926 (18.9%)
sendforward: 505,452 (11.8%)
opt_eq: 451,754 (10.5%)
opt_plus: 74,404 ( 1.7%)
opt_minus: 36,228 ( 0.8%)
opt_send_without_block: 21,792 ( 0.5%)
opt_neq: 7,231 ( 0.2%)
opt_mult: 6,752 ( 0.2%)
opt_or: 3,753 ( 0.1%)
opt_lt: 348 ( 0.0%)
opt_ge: 91 ( 0.0%)
opt_gt: 36 ( 0.0%)
Top-9 send fallback reasons (100.0% of total 25,530,724):
send_without_block_polymorphic: 9,722,491 (38.1%)
send_no_profiles: 5,894,788 (23.1%)
send_without_block_not_optimized_method_type: 4,523,682 (17.7%)
not_optimized_instruction: 4,293,171 (16.8%)
send_without_block_no_profiles: 998,746 ( 3.9%)
send_not_optimized_method_type: 72,318 ( 0.3%)
send_without_block_cfunc_array_variadic: 15,134 ( 0.1%)
obj_to_string_not_string: 9,765 ( 0.0%)
send_without_block_direct_too_many_args: 629 ( 0.0%)
Top-9 unhandled YARV insns (100.0% of total 690,950):
expandarray: 328,490 (47.5%)
checkkeyword: 190,694 (27.6%)
getclassvariable: 59,901 ( 8.7%)
invokesuperforward: 49,503 ( 7.2%)
getblockparam: 49,119 ( 7.1%)
opt_duparray_send: 11,978 ( 1.7%)
getconstant: 952 ( 0.1%)
checkmatch: 290 ( 0.0%)
once: 23 ( 0.0%)
Top-3 compile error reasons (100.0% of total 3,718,636):
register_spill_on_alloc: 3,418,255 (91.9%)
register_spill_on_ccall: 182,018 ( 4.9%)
exception_handler: 118,363 ( 3.2%)
Top-14 side exit reasons (100.0% of total 10,860,385):
compile_error: 3,718,636 (34.2%)
guard_type_failure: 2,638,926 (24.3%)
guard_shape_failure: 1,917,209 (17.7%)
unhandled_yarv_insn: 690,950 ( 6.4%)
block_param_proxy_not_iseq_or_ifunc: 535,789 ( 4.9%)
unhandled_kwarg: 455,347 ( 4.2%)
patchpoint: 370,476 ( 3.4%)
unknown_newarray_send: 314,786 ( 2.9%)
unhandled_splat: 122,071 ( 1.1%)
unhandled_hir_insn: 76,397 ( 0.7%)
block_param_proxy_modified: 19,193 ( 0.2%)
obj_to_string_fallback: 566 ( 0.0%)
guard_type_not_failure: 22 ( 0.0%)
interrupt: 17 ( 0.0%)
send_count: 62,244,604
dynamic_send_count: 25,530,724 (41.0%)
optimized_send_count: 36,713,880 (59.0%)
iseq_optimized_send_count: 18,587,512 (29.9%)
inline_cfunc_optimized_send_count: 7,086,414 (11.4%)
non_variadic_cfunc_optimized_send_count: 8,375,754 (13.5%)
variadic_cfunc_optimized_send_count: 2,664,200 ( 4.3%)
dynamic_getivar_count: 7,365,995
dynamic_setivar_count: 7,245,005
compiled_iseq_count: 4,796
failed_iseq_count: 447
compile_time: 814ms
profile_time: 9ms
gc_time: 9ms
invalidation_time: 72ms
vm_write_pc_count: 64,156,223
vm_write_sp_count: 62,812,449
vm_write_locals_count: 62,812,449
vm_write_stack_count: 62,812,449
vm_write_to_parent_iseq_local_count: 292,458
vm_read_from_parent_iseq_local_count: 6,599,701
code_region_bytes: 22,953,984
side_exit_count: 10,860,385
total_insn_count: 517,606,340
vm_insn_count: 162,979,530
zjit_insn_count: 354,626,810
ratio_in_zjit: 68.5%
```
</details>
lobsters after:
<details>
```
***ZJIT: Printing ZJIT statistics on exit***
Top-20 not inlined C methods (59.9% of total 11,291,815):
Kernel#is_a?: 1,046,269 ( 9.3%)
String#<<: 851,954 ( 7.5%)
Hash#[]=: 743,274 ( 6.6%)
Regexp#match?: 399,894 ( 3.5%)
String#empty?: 353,775 ( 3.1%)
Hash#key?: 349,147 ( 3.1%)
String#start_with?: 334,961 ( 3.0%)
Kernel#respond_to?: 316,502 ( 2.8%)
ObjectSpace::WeakKeyMap#[]: 238,978 ( 2.1%)
TrueClass#===: 235,771 ( 2.1%)
FalseClass#===: 231,144 ( 2.0%)
String#sub!: 219,579 ( 1.9%)
Array#include?: 211,385 ( 1.9%)
Hash#fetch: 204,702 ( 1.8%)
Kernel#block_given?: 181,797 ( 1.6%)
Kernel#dup: 179,341 ( 1.6%)
BasicObject#!=: 175,997 ( 1.6%)
Class#new: 168,079 ( 1.5%)
Kernel#kind_of?: 165,600 ( 1.5%)
String#==: 157,742 ( 1.4%)
Top-20 not annotated C methods (60.9% of total 11,466,928):
Kernel#is_a?: 1,239,923 (10.8%)
String#<<: 851,954 ( 7.4%)
Hash#[]=: 743,453 ( 6.5%)
Regexp#match?: 399,894 ( 3.5%)
String#empty?: 361,013 ( 3.1%)
Hash#key?: 349,147 ( 3.0%)
String#start_with?: 334,961 ( 2.9%)
Kernel#respond_to?: 316,502 ( 2.8%)
ObjectSpace::WeakKeyMap#[]: 238,978 ( 2.1%)
TrueClass#===: 235,771 ( 2.1%)
FalseClass#===: 231,144 ( 2.0%)
String#sub!: 219,579 ( 1.9%)
Array#include?: 211,385 ( 1.8%)
Hash#fetch: 204,702 ( 1.8%)
Kernel#block_given?: 191,666 ( 1.7%)
Kernel#dup: 179,348 ( 1.6%)
BasicObject#!=: 176,181 ( 1.5%)
Class#new: 168,079 ( 1.5%)
Kernel#kind_of?: 165,634 ( 1.4%)
String#==: 163,674 ( 1.4%)
Top-2 not optimized method types for send (100.0% of total 72,318):
cfunc: 48,055 (66.4%)
iseq: 24,263 (33.6%)
Top-6 not optimized method types for send_without_block (100.0% of total 4,524,016):
iseq: 2,272,269 (50.2%)
bmethod: 985,636 (21.8%)
optimized: 949,704 (21.0%)
alias: 310,747 ( 6.9%)
null: 5,106 ( 0.1%)
cfunc: 554 ( 0.0%)
Top-13 not optimized instructions (100.0% of total 4,294,241):
invokesuper: 2,375,446 (55.3%)
invokeblock: 810,955 (18.9%)
sendforward: 505,451 (11.8%)
opt_eq: 451,754 (10.5%)
opt_plus: 74,404 ( 1.7%)
opt_minus: 36,228 ( 0.8%)
opt_send_without_block: 21,792 ( 0.5%)
opt_neq: 7,231 ( 0.2%)
opt_mult: 6,752 ( 0.2%)
opt_or: 3,753 ( 0.1%)
opt_lt: 348 ( 0.0%)
opt_ge: 91 ( 0.0%)
opt_gt: 36 ( 0.0%)
Top-9 send fallback reasons (100.0% of total 25,534,542):
send_without_block_polymorphic: 9,723,469 (38.1%)
send_no_profiles: 5,896,023 (23.1%)
send_without_block_not_optimized_method_type: 4,524,016 (17.7%)
not_optimized_instruction: 4,294,241 (16.8%)
send_without_block_no_profiles: 998,947 ( 3.9%)
send_not_optimized_method_type: 72,318 ( 0.3%)
send_without_block_cfunc_array_variadic: 15,134 ( 0.1%)
obj_to_string_not_string: 9,765 ( 0.0%)
send_without_block_direct_too_many_args: 629 ( 0.0%)
Top-8 unhandled YARV insns (100.0% of total 362,460):
checkkeyword: 190,694 (52.6%)
getclassvariable: 59,901 (16.5%)
invokesuperforward: 49,503 (13.7%)
getblockparam: 49,119 (13.6%)
opt_duparray_send: 11,978 ( 3.3%)
getconstant: 952 ( 0.3%)
checkmatch: 290 ( 0.1%)
once: 23 ( 0.0%)
Top-3 compile error reasons (100.0% of total 3,798,744):
register_spill_on_alloc: 3,495,669 (92.0%)
register_spill_on_ccall: 184,712 ( 4.9%)
exception_handler: 118,363 ( 3.1%)
Top-15 side exit reasons (100.0% of total 10,637,319):
compile_error: 3,798,744 (35.7%)
guard_type_failure: 2,655,504 (25.0%)
guard_shape_failure: 1,917,217 (18.0%)
block_param_proxy_not_iseq_or_ifunc: 535,789 ( 5.0%)
unhandled_kwarg: 455,492 ( 4.3%)
patchpoint: 370,478 ( 3.5%)
unhandled_yarv_insn: 362,460 ( 3.4%)
unknown_newarray_send: 314,786 ( 3.0%)
unhandled_splat: 122,071 ( 1.1%)
unhandled_hir_insn: 83,066 ( 0.8%)
block_param_proxy_modified: 19,193 ( 0.2%)
guard_int_equals_failure: 1,914 ( 0.0%)
obj_to_string_fallback: 566 ( 0.0%)
guard_type_not_failure: 22 ( 0.0%)
interrupt: 17 ( 0.0%)
send_count: 62,495,067
dynamic_send_count: 25,534,542 (40.9%)
optimized_send_count: 36,960,525 (59.1%)
iseq_optimized_send_count: 18,582,072 (29.7%)
inline_cfunc_optimized_send_count: 7,086,638 (11.3%)
non_variadic_cfunc_optimized_send_count: 8,392,657 (13.4%)
variadic_cfunc_optimized_send_count: 2,899,158 ( 4.6%)
dynamic_getivar_count: 7,365,994
dynamic_setivar_count: 7,248,500
compiled_iseq_count: 4,780
failed_iseq_count: 463
compile_time: 816ms
profile_time: 9ms
gc_time: 11ms
invalidation_time: 70ms
vm_write_pc_count: 64,363,541
vm_write_sp_count: 63,022,221
vm_write_locals_count: 63,022,221
vm_write_stack_count: 63,022,221
vm_write_to_parent_iseq_local_count: 292,458
vm_read_from_parent_iseq_local_count: 6,850,977
code_region_bytes: 23,019,520
side_exit_count: 10,637,319
total_insn_count: 517,303,190
vm_insn_count: 160,562,103
zjit_insn_count: 356,741,087
ratio_in_zjit: 69.0%
```
</details>
railsbench before:
<details>
```
***ZJIT: Printing ZJIT statistics on exit***
Top-20 not inlined C methods (66.1% of total 25,524,934):
Hash#[]=: 1,700,237 ( 6.7%)
String#getbyte: 1,572,123 ( 6.2%)
String#<<: 1,494,022 ( 5.9%)
Kernel#is_a?: 1,429,930 ( 5.6%)
String#empty?: 1,370,323 ( 5.4%)
Regexp#match?: 1,235,067 ( 4.8%)
Kernel#respond_to?: 1,198,251 ( 4.7%)
Hash#key?: 1,087,406 ( 4.3%)
String#setbyte: 810,022 ( 3.2%)
Integer#^: 766,624 ( 3.0%)
Kernel#block_given?: 603,613 ( 2.4%)
String#==: 590,409 ( 2.3%)
Class#new: 506,216 ( 2.0%)
Hash#delete: 455,288 ( 1.8%)
BasicObject#!=: 428,771 ( 1.7%)
Hash#fetch: 408,621 ( 1.6%)
String#ascii_only?: 373,915 ( 1.5%)
ObjectSpace::WeakKeyMap#[]: 287,957 ( 1.1%)
NilClass#===: 277,244 ( 1.1%)
Kernel#Array: 269,590 ( 1.1%)
Top-20 not annotated C methods (66.8% of total 25,392,654):
Hash#[]=: 1,700,416 ( 6.7%)
String#getbyte: 1,572,123 ( 6.2%)
Kernel#is_a?: 1,515,672 ( 6.0%)
String#<<: 1,494,022 ( 5.9%)
String#empty?: 1,370,478 ( 5.4%)
Regexp#match?: 1,235,067 ( 4.9%)
Kernel#respond_to?: 1,198,251 ( 4.7%)
Hash#key?: 1,087,406 ( 4.3%)
String#setbyte: 810,022 ( 3.2%)
Integer#^: 766,624 ( 3.0%)
Kernel#block_given?: 603,613 ( 2.4%)
String#==: 601,115 ( 2.4%)
Class#new: 506,216 ( 2.0%)
Hash#delete: 455,288 ( 1.8%)
BasicObject#!=: 428,876 ( 1.7%)
Hash#fetch: 408,621 ( 1.6%)
String#ascii_only?: 373,915 ( 1.5%)
ObjectSpace::WeakKeyMap#[]: 287,957 ( 1.1%)
NilClass#===: 277,244 ( 1.1%)
Kernel#Array: 269,590 ( 1.1%)
Top-2 not optimized method types for send (100.0% of total 186,159):
iseq: 112,747 (60.6%)
cfunc: 73,412 (39.4%)
Top-6 not optimized method types for send_without_block (100.0% of total 8,142,248):
iseq: 3,464,671 (42.6%)
optimized: 2,632,884 (32.3%)
bmethod: 1,290,701 (15.9%)
alias: 706,020 ( 8.7%)
null: 47,942 ( 0.6%)
cfunc: 30 ( 0.0%)
Top-11 not optimized instructions (100.0% of total 8,394,873):
invokesuper: 5,602,274 (66.7%)
invokeblock: 1,764,936 (21.0%)
sendforward: 551,832 ( 6.6%)
opt_eq: 441,959 ( 5.3%)
opt_plus: 31,635 ( 0.4%)
opt_send_without_block: 1,163 ( 0.0%)
opt_lt: 372 ( 0.0%)
opt_mult: 251 ( 0.0%)
opt_ge: 193 ( 0.0%)
opt_neq: 149 ( 0.0%)
opt_or: 109 ( 0.0%)
Top-8 send fallback reasons (100.0% of total 40,748,753):
send_without_block_polymorphic: 12,933,923 (31.7%)
send_no_profiles: 9,033,636 (22.2%)
not_optimized_instruction: 8,394,873 (20.6%)
send_without_block_not_optimized_method_type: 8,142,248 (20.0%)
send_without_block_no_profiles: 1,839,228 ( 4.5%)
send_without_block_cfunc_array_variadic: 215,046 ( 0.5%)
send_not_optimized_method_type: 186,159 ( 0.5%)
obj_to_string_not_string: 3,640 ( 0.0%)
Top-9 unhandled YARV insns (100.0% of total 1,604,456):
getclassvariable: 458,136 (28.6%)
getblockparam: 455,921 (28.4%)
checkkeyword: 265,425 (16.5%)
invokesuperforward: 239,383 (14.9%)
expandarray: 137,305 ( 8.6%)
getconstant: 48,100 ( 3.0%)
checkmatch: 149 ( 0.0%)
once: 23 ( 0.0%)
opt_duparray_send: 14 ( 0.0%)
Top-3 compile error reasons (100.0% of total 5,570,130):
register_spill_on_alloc: 4,994,130 (89.7%)
exception_handler: 356,784 ( 6.4%)
register_spill_on_ccall: 219,216 ( 3.9%)
Top-13 side exit reasons (100.0% of total 12,412,181):
compile_error: 5,570,130 (44.9%)
unhandled_yarv_insn: 1,604,456 (12.9%)
guard_shape_failure: 1,462,872 (11.8%)
guard_type_failure: 845,891 ( 6.8%)
block_param_proxy_not_iseq_or_ifunc: 765,968 ( 6.2%)
unhandled_kwarg: 658,341 ( 5.3%)
patchpoint: 504,437 ( 4.1%)
unhandled_splat: 446,990 ( 3.6%)
unknown_newarray_send: 332,740 ( 2.7%)
unhandled_hir_insn: 160,205 ( 1.3%)
block_param_proxy_modified: 59,589 ( 0.5%)
obj_to_string_fallback: 553 ( 0.0%)
interrupt: 9 ( 0.0%)
send_count: 119,067,587
dynamic_send_count: 40,748,753 (34.2%)
optimized_send_count: 78,318,834 (65.8%)
iseq_optimized_send_count: 39,936,542 (33.5%)
inline_cfunc_optimized_send_count: 12,857,358 (10.8%)
non_variadic_cfunc_optimized_send_count: 19,722,584 (16.6%)
variadic_cfunc_optimized_send_count: 5,802,350 ( 4.9%)
dynamic_getivar_count: 10,980,323
dynamic_setivar_count: 12,962,726
compiled_iseq_count: 2,531
failed_iseq_count: 245
compile_time: 414ms
profile_time: 21ms
gc_time: 33ms
invalidation_time: 5ms
vm_write_pc_count: 129,093,714
vm_write_sp_count: 126,023,084
vm_write_locals_count: 126,023,084
vm_write_stack_count: 126,023,084
vm_write_to_parent_iseq_local_count: 385,461
vm_read_from_parent_iseq_local_count: 11,266,484
code_region_bytes: 12,156,928
side_exit_count: 12,412,181
total_insn_count: 866,780,158
vm_insn_count: 216,821,134
zjit_insn_count: 649,959,024
ratio_in_zjit: 75.0%
```
</details>
railsbench after:
<details>
```
***ZJIT: Printing ZJIT statistics on exit***
Top-20 not inlined C methods (66.0% of total 25,597,895):
Hash#[]=: 1,724,042 ( 6.7%)
String#getbyte: 1,572,123 ( 6.1%)
String#<<: 1,494,022 ( 5.8%)
Kernel#is_a?: 1,429,946 ( 5.6%)
String#empty?: 1,370,323 ( 5.4%)
Regexp#match?: 1,235,067 ( 4.8%)
Kernel#respond_to?: 1,198,251 ( 4.7%)
Hash#key?: 1,087,406 ( 4.2%)
String#setbyte: 810,022 ( 3.2%)
Integer#^: 766,624 ( 3.0%)
Kernel#block_given?: 603,613 ( 2.4%)
String#==: 590,699 ( 2.3%)
Class#new: 506,216 ( 2.0%)
Hash#delete: 455,288 ( 1.8%)
BasicObject#!=: 428,771 ( 1.7%)
Hash#fetch: 408,621 ( 1.6%)
String#ascii_only?: 373,915 ( 1.5%)
ObjectSpace::WeakKeyMap#[]: 287,957 ( 1.1%)
NilClass#===: 277,244 ( 1.1%)
Kernel#Array: 269,590 ( 1.1%)
Top-20 not annotated C methods (66.7% of total 25,465,615):
Hash#[]=: 1,724,221 ( 6.8%)
String#getbyte: 1,572,123 ( 6.2%)
Kernel#is_a?: 1,515,688 ( 6.0%)
String#<<: 1,494,022 ( 5.9%)
String#empty?: 1,370,478 ( 5.4%)
Regexp#match?: 1,235,067 ( 4.8%)
Kernel#respond_to?: 1,198,251 ( 4.7%)
Hash#key?: 1,087,406 ( 4.3%)
String#setbyte: 810,022 ( 3.2%)
Integer#^: 766,624 ( 3.0%)
Kernel#block_given?: 603,613 ( 2.4%)
String#==: 601,405 ( 2.4%)
Class#new: 506,216 ( 2.0%)
Hash#delete: 455,288 ( 1.8%)
BasicObject#!=: 428,876 ( 1.7%)
Hash#fetch: 408,621 ( 1.6%)
String#ascii_only?: 373,915 ( 1.5%)
ObjectSpace::WeakKeyMap#[]: 287,957 ( 1.1%)
NilClass#===: 277,244 ( 1.1%)
Kernel#Array: 269,590 ( 1.1%)
Top-2 not optimized method types for send (100.0% of total 186,159):
iseq: 112,747 (60.6%)
cfunc: 73,412 (39.4%)
Top-6 not optimized method types for send_without_block (100.0% of total 8,142,248):
iseq: 3,464,671 (42.6%)
optimized: 2,632,884 (32.3%)
bmethod: 1,290,701 (15.9%)
alias: 706,020 ( 8.7%)
null: 47,942 ( 0.6%)
cfunc: 30 ( 0.0%)
Top-11 not optimized instructions (100.0% of total 8,442,456):
invokesuper: 5,649,857 (66.9%)
invokeblock: 1,764,936 (20.9%)
sendforward: 551,832 ( 6.5%)
opt_eq: 441,959 ( 5.2%)
opt_plus: 31,635 ( 0.4%)
opt_send_without_block: 1,163 ( 0.0%)
opt_lt: 372 ( 0.0%)
opt_mult: 251 ( 0.0%)
opt_ge: 193 ( 0.0%)
opt_neq: 149 ( 0.0%)
opt_or: 109 ( 0.0%)
Top-8 send fallback reasons (100.0% of total 40,796,314):
send_without_block_polymorphic: 12,933,921 (31.7%)
send_no_profiles: 9,033,616 (22.1%)
not_optimized_instruction: 8,442,456 (20.7%)
send_without_block_not_optimized_method_type: 8,142,248 (20.0%)
send_without_block_no_profiles: 1,839,228 ( 4.5%)
send_without_block_cfunc_array_variadic: 215,046 ( 0.5%)
send_not_optimized_method_type: 186,159 ( 0.5%)
obj_to_string_not_string: 3,640 ( 0.0%)
Top-8 unhandled YARV insns (100.0% of total 1,467,151):
getclassvariable: 458,136 (31.2%)
getblockparam: 455,921 (31.1%)
checkkeyword: 265,425 (18.1%)
invokesuperforward: 239,383 (16.3%)
getconstant: 48,100 ( 3.3%)
checkmatch: 149 ( 0.0%)
once: 23 ( 0.0%)
opt_duparray_send: 14 ( 0.0%)
Top-3 compile error reasons (100.0% of total 5,825,923):
register_spill_on_alloc: 5,225,940 (89.7%)
exception_handler: 356,784 ( 6.1%)
register_spill_on_ccall: 243,199 ( 4.2%)
Top-13 side exit reasons (100.0% of total 12,530,763):
compile_error: 5,825,923 (46.5%)
unhandled_yarv_insn: 1,467,151 (11.7%)
guard_shape_failure: 1,462,876 (11.7%)
guard_type_failure: 845,913 ( 6.8%)
block_param_proxy_not_iseq_or_ifunc: 765,968 ( 6.1%)
unhandled_kwarg: 658,341 ( 5.3%)
patchpoint: 504,437 ( 4.0%)
unhandled_splat: 446,990 ( 3.6%)
unknown_newarray_send: 332,740 ( 2.7%)
unhandled_hir_insn: 160,273 ( 1.3%)
block_param_proxy_modified: 59,589 ( 0.5%)
obj_to_string_fallback: 553 ( 0.0%)
interrupt: 9 ( 0.0%)
send_count: 119,163,569
dynamic_send_count: 40,796,314 (34.2%)
optimized_send_count: 78,367,255 (65.8%)
iseq_optimized_send_count: 39,911,967 (33.5%)
inline_cfunc_optimized_send_count: 12,857,393 (10.8%)
non_variadic_cfunc_optimized_send_count: 19,770,401 (16.6%)
variadic_cfunc_optimized_send_count: 5,827,494 ( 4.9%)
dynamic_getivar_count: 10,980,323
dynamic_setivar_count: 12,986,381
compiled_iseq_count: 2,523
failed_iseq_count: 252
compile_time: 420ms
profile_time: 21ms
gc_time: 30ms
invalidation_time: 4ms
vm_write_pc_count: 128,973,665
vm_write_sp_count: 125,926,968
vm_write_locals_count: 125,926,968
vm_write_stack_count: 125,926,968
vm_write_to_parent_iseq_local_count: 385,752
vm_read_from_parent_iseq_local_count: 11,267,766
code_region_bytes: 12,189,696
side_exit_count: 12,530,763
total_insn_count: 866,667,490
vm_insn_count: 217,813,201
zjit_insn_count: 648,854,289
ratio_in_zjit: 74.9%
```
</details>
This commit is contained in:
parent
6eb75f6c36
commit
fba349e658
Notes:
git
2025-10-20 14:56:21 +00:00
Merged-By: tekknolagi <donotemailthisaddress@bernsteinbear.com>
6
jit.c
6
jit.c
@ -450,6 +450,12 @@ rb_yarv_ary_entry_internal(VALUE ary, long offset)
|
||||
return rb_ary_entry_internal(ary, offset);
|
||||
}
|
||||
|
||||
long
|
||||
rb_jit_array_len(VALUE a)
|
||||
{
|
||||
return rb_array_len(a);
|
||||
}
|
||||
|
||||
void
|
||||
rb_set_cfp_pc(struct rb_control_frame_struct *cfp, const VALUE *pc)
|
||||
{
|
||||
|
||||
@ -1714,6 +1714,36 @@ class TestZJIT < Test::Unit::TestCase
|
||||
}, call_threshold: 1, insns: [:opt_getconstant_path]
|
||||
end
|
||||
|
||||
def test_expandarray_no_splat
|
||||
assert_compiles '[3, 4]', %q{
|
||||
def test(o)
|
||||
a, b = o
|
||||
[a, b]
|
||||
end
|
||||
test [3, 4]
|
||||
}, call_threshold: 1, insns: [:expandarray]
|
||||
end
|
||||
|
||||
def test_expandarray_splat
|
||||
assert_compiles '[3, [4]]', %q{
|
||||
def test(o)
|
||||
a, *b = o
|
||||
[a, b]
|
||||
end
|
||||
test [3, 4]
|
||||
}, call_threshold: 1, insns: [:expandarray]
|
||||
end
|
||||
|
||||
def test_expandarray_splat_post
|
||||
assert_compiles '[3, [4], 5]', %q{
|
||||
def test(o)
|
||||
a, *b, c = o
|
||||
[a, b, c]
|
||||
end
|
||||
test [3, 4, 5]
|
||||
}, call_threshold: 1, insns: [:expandarray]
|
||||
end
|
||||
|
||||
def test_getconstant_path_autoload
|
||||
# A constant-referencing expression can run arbitrary code through Kernel#autoload.
|
||||
Dir.mktmpdir('autoload') do |tmpdir|
|
||||
|
||||
6
yjit.c
6
yjit.c
@ -69,12 +69,6 @@ STATIC_ASSERT(pointer_tagging_scheme, USE_FLONUM);
|
||||
// The "_yjit_" part is for trying to be informative. We might want different
|
||||
// suffixes for symbols meant for Rust and symbols meant for broader CRuby.
|
||||
|
||||
long
|
||||
rb_yjit_array_len(VALUE a)
|
||||
{
|
||||
return rb_array_len(a);
|
||||
}
|
||||
|
||||
# define PTR2NUM(x) (rb_int2inum((intptr_t)(void *)(x)))
|
||||
|
||||
// For a given raw_sample (frame), set the hash with the caller's
|
||||
|
||||
@ -381,7 +381,7 @@ fn main() {
|
||||
.allowlist_function("rb_METHOD_ENTRY_VISI")
|
||||
.allowlist_function("rb_RCLASS_ORIGIN")
|
||||
.allowlist_function("rb_method_basic_definition_p")
|
||||
.allowlist_function("rb_yjit_array_len")
|
||||
.allowlist_function("rb_jit_array_len")
|
||||
.allowlist_function("rb_obj_class")
|
||||
.allowlist_function("rb_obj_is_proc")
|
||||
.allowlist_function("rb_vm_base_ptr")
|
||||
|
||||
@ -2305,7 +2305,7 @@ fn gen_expandarray(
|
||||
}
|
||||
|
||||
// Get the compile-time array length
|
||||
let comptime_len = unsafe { rb_yjit_array_len(comptime_recv) as u32 };
|
||||
let comptime_len = unsafe { rb_jit_array_len(comptime_recv) as u32 };
|
||||
|
||||
// Move the array from the stack and check that it's an array.
|
||||
guard_object_is_array(
|
||||
@ -7603,7 +7603,7 @@ fn gen_send_iseq(
|
||||
gen_counter_incr(jit, asm, Counter::send_iseq_splat_not_array);
|
||||
return None;
|
||||
} else {
|
||||
unsafe { rb_yjit_array_len(array) as u32}
|
||||
unsafe { rb_jit_array_len(array) as u32}
|
||||
};
|
||||
|
||||
// Arity check accounting for size of the splat. When callee has rest parameters, we insert
|
||||
|
||||
2
yjit/src/cruby_bindings.inc.rs
generated
2
yjit/src/cruby_bindings.inc.rs
generated
@ -1113,7 +1113,6 @@ extern "C" {
|
||||
lines: *mut ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
pub fn rb_jit_cont_each_iseq(callback: rb_iseq_callback, data: *mut ::std::os::raw::c_void);
|
||||
pub fn rb_yjit_array_len(a: VALUE) -> ::std::os::raw::c_long;
|
||||
pub fn rb_yjit_exit_locations_dict(
|
||||
yjit_raw_samples: *mut VALUE,
|
||||
yjit_line_samples: *mut ::std::os::raw::c_int,
|
||||
@ -1250,6 +1249,7 @@ extern "C" {
|
||||
pub fn rb_IMEMO_TYPE_P(imemo: VALUE, imemo_type: imemo_type) -> ::std::os::raw::c_int;
|
||||
pub fn rb_assert_cme_handle(handle: VALUE);
|
||||
pub fn rb_yarv_ary_entry_internal(ary: VALUE, offset: ::std::os::raw::c_long) -> VALUE;
|
||||
pub fn rb_jit_array_len(a: VALUE) -> ::std::os::raw::c_long;
|
||||
pub fn rb_set_cfp_pc(cfp: *mut rb_control_frame_struct, pc: *const VALUE);
|
||||
pub fn rb_set_cfp_sp(cfp: *mut rb_control_frame_struct, sp: *mut VALUE);
|
||||
pub fn rb_jit_shape_too_complex_p(shape_id: shape_id_t) -> bool;
|
||||
|
||||
@ -272,6 +272,7 @@ fn main() {
|
||||
.allowlist_function("rb_jit_mark_executable")
|
||||
.allowlist_function("rb_jit_mark_unused")
|
||||
.allowlist_function("rb_jit_get_page_size")
|
||||
.allowlist_function("rb_jit_array_len")
|
||||
.allowlist_function("rb_zjit_iseq_builtin_attrs")
|
||||
.allowlist_function("rb_zjit_iseq_inspect")
|
||||
.allowlist_function("rb_zjit_iseq_insn_set")
|
||||
|
||||
@ -356,6 +356,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
|
||||
Insn::NewRangeFixnum { low, high, flag, state } => gen_new_range_fixnum(asm, opnd!(low), opnd!(high), *flag, &function.frame_state(*state)),
|
||||
Insn::ArrayDup { val, state } => gen_array_dup(asm, opnd!(val), &function.frame_state(*state)),
|
||||
Insn::ArrayArefFixnum { array, index, .. } => gen_aref_fixnum(asm, opnd!(array), opnd!(index)),
|
||||
Insn::ArrayLength { array } => gen_array_length(asm, opnd!(array)),
|
||||
Insn::ObjectAlloc { val, state } => gen_object_alloc(jit, asm, opnd!(val), &function.frame_state(*state)),
|
||||
&Insn::ObjectAllocClass { class, state } => gen_object_alloc_class(asm, class, &function.frame_state(state)),
|
||||
Insn::StringCopy { val, chilled, state } => gen_string_copy(asm, opnd!(val), *chilled, &function.frame_state(*state)),
|
||||
@ -1258,6 +1259,10 @@ fn gen_aref_fixnum(
|
||||
asm_ccall!(asm, rb_ary_entry, array, unboxed_idx)
|
||||
}
|
||||
|
||||
fn gen_array_length(asm: &mut Assembler, array: Opnd) -> lir::Opnd {
|
||||
asm_ccall!(asm, rb_jit_array_len, array)
|
||||
}
|
||||
|
||||
/// Compile a new hash instruction
|
||||
fn gen_new_hash(
|
||||
jit: &mut JITState,
|
||||
@ -1589,8 +1594,13 @@ fn gen_guard_type_not(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, g
|
||||
}
|
||||
|
||||
/// Compile an identity check with a side exit
|
||||
fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: VALUE, state: &FrameState) -> lir::Opnd {
|
||||
asm.cmp(val, Opnd::Value(expected));
|
||||
fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: crate::hir::Const, state: &FrameState) -> lir::Opnd {
|
||||
let expected_opnd: Opnd = match expected {
|
||||
crate::hir::Const::Value(v) => { Opnd::Value(v) }
|
||||
crate::hir::Const::CInt64(v) => { v.into() }
|
||||
_ => panic!("gen_guard_bit_equals: unexpected hir::Const {:?}", expected),
|
||||
};
|
||||
asm.cmp(val, expected_opnd);
|
||||
asm.jnz(side_exit(jit, state, GuardBitEquals(expected)));
|
||||
val
|
||||
}
|
||||
|
||||
1
zjit/src/cruby_bindings.inc.rs
generated
1
zjit/src/cruby_bindings.inc.rs
generated
@ -1045,6 +1045,7 @@ unsafe extern "C" {
|
||||
pub fn rb_IMEMO_TYPE_P(imemo: VALUE, imemo_type: imemo_type) -> ::std::os::raw::c_int;
|
||||
pub fn rb_assert_cme_handle(handle: VALUE);
|
||||
pub fn rb_yarv_ary_entry_internal(ary: VALUE, offset: ::std::os::raw::c_long) -> VALUE;
|
||||
pub fn rb_jit_array_len(a: VALUE) -> ::std::os::raw::c_long;
|
||||
pub fn rb_set_cfp_pc(cfp: *mut rb_control_frame_struct, pc: *const VALUE);
|
||||
pub fn rb_set_cfp_sp(cfp: *mut rb_control_frame_struct, sp: *mut VALUE);
|
||||
pub fn rb_jit_shape_too_complex_p(shape_id: shape_id_t) -> bool;
|
||||
|
||||
137
zjit/src/hir.rs
137
zjit/src/hir.rs
@ -270,7 +270,7 @@ impl<'a> std::fmt::Display for InvariantPrinter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||
pub enum Const {
|
||||
Value(VALUE),
|
||||
CBool(bool),
|
||||
@ -460,7 +460,7 @@ pub enum SideExitReason {
|
||||
GuardType(Type),
|
||||
GuardTypeNot(Type),
|
||||
GuardShape(ShapeId),
|
||||
GuardBitEquals(VALUE),
|
||||
GuardBitEquals(Const),
|
||||
PatchPoint(Invariant),
|
||||
CalleeSideExit,
|
||||
ObjToStringFallback,
|
||||
@ -583,6 +583,8 @@ pub enum Insn {
|
||||
/// Push `val` onto `array`, where `array` is already `Array`.
|
||||
ArrayPush { array: InsnId, val: InsnId, state: InsnId },
|
||||
ArrayArefFixnum { array: InsnId, index: InsnId },
|
||||
/// Return the length of the array as a C `long` ([`types::CInt64`])
|
||||
ArrayLength { array: InsnId },
|
||||
|
||||
HashAref { hash: InsnId, key: InsnId, state: InsnId },
|
||||
HashDup { val: InsnId, state: InsnId },
|
||||
@ -768,8 +770,8 @@ pub enum Insn {
|
||||
/// Side-exit if val doesn't have the expected type.
|
||||
GuardType { val: InsnId, guard_type: Type, state: InsnId },
|
||||
GuardTypeNot { val: InsnId, guard_type: Type, state: InsnId },
|
||||
/// Side-exit if val is not the expected VALUE.
|
||||
GuardBitEquals { val: InsnId, expected: VALUE, state: InsnId },
|
||||
/// Side-exit if val is not the expected Const.
|
||||
GuardBitEquals { val: InsnId, expected: Const, state: InsnId },
|
||||
/// Side-exit if val doesn't have the expected shape.
|
||||
GuardShape { val: InsnId, shape: ShapeId, state: InsnId },
|
||||
/// Side-exit if the block param has been modified or the block handler for the frame
|
||||
@ -899,6 +901,9 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
|
||||
Insn::ArrayArefFixnum { array, index, .. } => {
|
||||
write!(f, "ArrayArefFixnum {array}, {index}")
|
||||
}
|
||||
Insn::ArrayLength { array } => {
|
||||
write!(f, "ArrayLength {array}")
|
||||
}
|
||||
Insn::NewHash { elements, .. } => {
|
||||
write!(f, "NewHash")?;
|
||||
let mut prefix = " ";
|
||||
@ -1604,6 +1609,7 @@ impl Function {
|
||||
&NewRange { low, high, flag, state } => NewRange { low: find!(low), high: find!(high), flag, state: find!(state) },
|
||||
&NewRangeFixnum { low, high, flag, state } => NewRangeFixnum { low: find!(low), high: find!(high), flag, state: find!(state) },
|
||||
&ArrayArefFixnum { array, index } => ArrayArefFixnum { array: find!(array), index: find!(index) },
|
||||
&ArrayLength { array } => ArrayLength { array: find!(array) },
|
||||
&ArrayMax { ref elements, state } => ArrayMax { elements: find_vec!(elements), state: find!(state) },
|
||||
&SetGlobal { id, val, state } => SetGlobal { id, val: find!(val), state },
|
||||
&GetIvar { self_val, id, state } => GetIvar { self_val: find!(self_val), id, state },
|
||||
@ -1691,6 +1697,7 @@ impl Function {
|
||||
Insn::NewArray { .. } => types::ArrayExact,
|
||||
Insn::ArrayDup { .. } => types::ArrayExact,
|
||||
Insn::ArrayArefFixnum { .. } => types::BasicObject,
|
||||
Insn::ArrayLength { .. } => types::CInt64,
|
||||
Insn::HashAref { .. } => types::BasicObject,
|
||||
Insn::NewHash { .. } => types::HashExact,
|
||||
Insn::HashDup { .. } => types::HashExact,
|
||||
@ -1703,7 +1710,7 @@ impl Function {
|
||||
&Insn::CCallVariadic { return_type, .. } => return_type,
|
||||
Insn::GuardType { val, guard_type, .. } => self.type_of(*val).intersection(*guard_type),
|
||||
Insn::GuardTypeNot { .. } => types::BasicObject,
|
||||
Insn::GuardBitEquals { val, expected, .. } => self.type_of(*val).intersection(Type::from_value(*expected)),
|
||||
Insn::GuardBitEquals { val, expected, .. } => self.type_of(*val).intersection(Type::from_const(*expected)),
|
||||
Insn::GuardShape { val, .. } => self.type_of(*val),
|
||||
Insn::FixnumAdd { .. } => types::Fixnum,
|
||||
Insn::FixnumSub { .. } => types::Fixnum,
|
||||
@ -2803,6 +2810,9 @@ impl Function {
|
||||
worklist.push_back(array);
|
||||
worklist.push_back(index);
|
||||
}
|
||||
&Insn::ArrayLength { array } => {
|
||||
worklist.push_back(array);
|
||||
}
|
||||
&Insn::HashAref { hash, key, state } => {
|
||||
worklist.push_back(hash);
|
||||
worklist.push_back(key);
|
||||
@ -4428,6 +4438,31 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
||||
state.stack_push(result);
|
||||
}
|
||||
}
|
||||
YARVINSN_expandarray => {
|
||||
let num = get_arg(pc, 0).as_u64();
|
||||
let flag = get_arg(pc, 1).as_u64();
|
||||
if flag != 0 {
|
||||
// We don't (yet) handle 0x01 (rest args), 0x02 (post args), or 0x04
|
||||
// (reverse?)
|
||||
//
|
||||
// Unhandled opcode; side-exit into the interpreter
|
||||
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
|
||||
fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::UnhandledYARVInsn(opcode) });
|
||||
break; // End the block
|
||||
}
|
||||
let val = state.stack_pop()?;
|
||||
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
|
||||
let array = fun.push_insn(block, Insn::GuardType { val, guard_type: types::ArrayExact, state: exit_id, });
|
||||
let length = fun.push_insn(block, Insn::ArrayLength { array });
|
||||
fun.push_insn(block, Insn::GuardBitEquals { val: length, expected: Const::CInt64(num as i64), state: exit_id });
|
||||
for i in (0..num).rev() {
|
||||
// TODO(max): Add a short-cut path for long indices into an array where the
|
||||
// index is known to be in-bounds
|
||||
let index = fun.push_insn(block, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(i.try_into().unwrap())) });
|
||||
let element = fun.push_insn(block, Insn::ArrayArefFixnum { array, index });
|
||||
state.stack_push(element);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Unhandled opcode; side-exit into the interpreter
|
||||
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
|
||||
@ -7914,6 +7949,98 @@ mod tests {
|
||||
Return v17
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expandarray_no_splat() {
|
||||
eval(r#"
|
||||
def test(o)
|
||||
a, b = o
|
||||
end
|
||||
"#);
|
||||
assert_contains_opcode("test", YARVINSN_expandarray);
|
||||
assert_snapshot!(hir_string("test"), @r"
|
||||
fn test@<compiled>:3:
|
||||
bb0():
|
||||
EntryPoint interpreter
|
||||
v1:BasicObject = LoadSelf
|
||||
v2:BasicObject = GetLocal l0, SP@6
|
||||
v3:NilClass = Const Value(nil)
|
||||
v4:NilClass = Const Value(nil)
|
||||
Jump bb2(v1, v2, v3, v4)
|
||||
bb1(v7:BasicObject, v8:BasicObject):
|
||||
EntryPoint JIT(0)
|
||||
v9:NilClass = Const Value(nil)
|
||||
v10:NilClass = Const Value(nil)
|
||||
Jump bb2(v7, v8, v9, v10)
|
||||
bb2(v12:BasicObject, v13:BasicObject, v14:NilClass, v15:NilClass):
|
||||
v20:ArrayExact = GuardType v13, ArrayExact
|
||||
v21:CInt64 = ArrayLength v20
|
||||
v22:CInt64[2] = GuardBitEquals v21, CInt64(2)
|
||||
v23:Fixnum[1] = Const Value(1)
|
||||
v24:BasicObject = ArrayArefFixnum v20, v23
|
||||
v25:Fixnum[0] = Const Value(0)
|
||||
v26:BasicObject = ArrayArefFixnum v20, v25
|
||||
PatchPoint NoEPEscape(test)
|
||||
CheckInterrupts
|
||||
Return v13
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expandarray_splat() {
|
||||
eval(r#"
|
||||
def test(o)
|
||||
a, *b = o
|
||||
end
|
||||
"#);
|
||||
assert_contains_opcode("test", YARVINSN_expandarray);
|
||||
assert_snapshot!(hir_string("test"), @r"
|
||||
fn test@<compiled>:3:
|
||||
bb0():
|
||||
EntryPoint interpreter
|
||||
v1:BasicObject = LoadSelf
|
||||
v2:BasicObject = GetLocal l0, SP@6
|
||||
v3:NilClass = Const Value(nil)
|
||||
v4:NilClass = Const Value(nil)
|
||||
Jump bb2(v1, v2, v3, v4)
|
||||
bb1(v7:BasicObject, v8:BasicObject):
|
||||
EntryPoint JIT(0)
|
||||
v9:NilClass = Const Value(nil)
|
||||
v10:NilClass = Const Value(nil)
|
||||
Jump bb2(v7, v8, v9, v10)
|
||||
bb2(v12:BasicObject, v13:BasicObject, v14:NilClass, v15:NilClass):
|
||||
SideExit UnhandledYARVInsn(expandarray)
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expandarray_splat_post() {
|
||||
eval(r#"
|
||||
def test(o)
|
||||
a, *b, c = o
|
||||
end
|
||||
"#);
|
||||
assert_contains_opcode("test", YARVINSN_expandarray);
|
||||
assert_snapshot!(hir_string("test"), @r"
|
||||
fn test@<compiled>:3:
|
||||
bb0():
|
||||
EntryPoint interpreter
|
||||
v1:BasicObject = LoadSelf
|
||||
v2:BasicObject = GetLocal l0, SP@7
|
||||
v3:NilClass = Const Value(nil)
|
||||
v4:NilClass = Const Value(nil)
|
||||
v5:NilClass = Const Value(nil)
|
||||
Jump bb2(v1, v2, v3, v4, v5)
|
||||
bb1(v8:BasicObject, v9:BasicObject):
|
||||
EntryPoint JIT(0)
|
||||
v10:NilClass = Const Value(nil)
|
||||
v11:NilClass = Const Value(nil)
|
||||
v12:NilClass = Const Value(nil)
|
||||
Jump bb2(v8, v9, v10, v11, v12)
|
||||
bb2(v14:BasicObject, v15:BasicObject, v16:NilClass, v17:NilClass, v18:NilClass):
|
||||
SideExit UnhandledYARVInsn(expandarray)
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -238,6 +238,23 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_const(val: Const) -> Type {
|
||||
match val {
|
||||
Const::Value(v) => Self::from_value(v),
|
||||
Const::CBool(v) => Self::from_cbool(v),
|
||||
Const::CInt8(v) => Self::from_cint(types::CInt8, v as i64),
|
||||
Const::CInt16(v) => Self::from_cint(types::CInt16, v as i64),
|
||||
Const::CInt32(v) => Self::from_cint(types::CInt32, v as i64),
|
||||
Const::CInt64(v) => Self::from_cint(types::CInt64, v as i64),
|
||||
Const::CUInt8(v) => Self::from_cint(types::CUInt8, v as i64),
|
||||
Const::CUInt16(v) => Self::from_cint(types::CUInt16, v as i64),
|
||||
Const::CUInt32(v) => Self::from_cint(types::CUInt32, v as i64),
|
||||
Const::CUInt64(v) => Self::from_cint(types::CUInt64, v as i64),
|
||||
Const::CPtr(v) => Self::from_cptr(v),
|
||||
Const::CDouble(v) => Self::from_double(v),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_profiled_type(val: ProfiledType) -> Type {
|
||||
if val.is_fixnum() { types::Fixnum }
|
||||
else if val.is_flonum() { types::Flonum }
|
||||
|
||||
@ -140,6 +140,7 @@ make_counters! {
|
||||
exit_guard_type_failure,
|
||||
exit_guard_type_not_failure,
|
||||
exit_guard_bit_equals_failure,
|
||||
exit_guard_int_equals_failure,
|
||||
exit_guard_shape_failure,
|
||||
exit_patchpoint_bop_redefined,
|
||||
exit_patchpoint_method_redefined,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user