@@ -944,45 +944,42 @@ new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int a
944
944
return new_insn_core (iseq , line_no , insn_id , argc , operands );
945
945
}
946
946
947
- static rb_call_info_t *
948
- new_callinfo (rb_iseq_t * iseq , ID mid , int argc , unsigned int flag , rb_call_info_kw_arg_t * kw_arg , int has_blockiseq )
947
+ static struct rb_call_info *
948
+ new_callinfo (rb_iseq_t * iseq , ID mid , int argc , unsigned int flag , struct rb_call_info_kw_arg * kw_arg , int has_blockiseq )
949
949
{
950
- rb_call_info_t * ci = (rb_call_info_t * )compile_data_alloc (iseq , sizeof (rb_call_info_t ));
950
+ size_t size = kw_arg != NULL ? sizeof (struct rb_call_info_with_kwarg ) : sizeof (struct rb_call_info );
951
+ struct rb_call_info * ci = (struct rb_call_info * )compile_data_alloc (iseq , size );
952
+ struct rb_call_info_with_kwarg * ci_kw = (struct rb_call_info_with_kwarg * )ci ;
951
953
952
954
ci -> mid = mid ;
953
955
ci -> flag = flag ;
954
956
ci -> orig_argc = argc ;
955
- ci -> argc = argc ;
956
- ci -> kw_arg = kw_arg ;
957
957
958
958
if (kw_arg ) {
959
- ci -> argc += kw_arg -> keyword_len ;
959
+ ci -> flag |= VM_CALL_KWARG ;
960
+ ci_kw -> kw_arg = kw_arg ;
960
961
ci -> orig_argc += kw_arg -> keyword_len ;
962
+ iseq -> body -> ci_kw_size ++ ;
963
+ }
964
+ else {
965
+ iseq -> body -> ci_size ++ ;
961
966
}
962
967
963
968
if (!(ci -> flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG )) &&
964
- ci -> kw_arg == NULL && !has_blockiseq ) {
969
+ kw_arg == NULL && !has_blockiseq ) {
965
970
ci -> flag |= VM_CALL_ARGS_SIMPLE ;
966
971
}
967
-
968
- ci -> method_state = 0 ;
969
- ci -> class_serial = 0 ;
970
- ci -> blockptr = 0 ;
971
- ci -> recv = Qundef ;
972
- ci -> call = 0 ; /* TODO: should set default function? */
973
-
974
- ci -> aux .index = iseq -> body -> callinfo_size ++ ;
975
-
976
972
return ci ;
977
973
}
978
974
979
975
static INSN *
980
- new_insn_send (rb_iseq_t * iseq , int line_no , ID id , VALUE argc , const rb_iseq_t * blockiseq , VALUE flag , rb_call_info_kw_arg_t * keywords )
976
+ new_insn_send (rb_iseq_t * iseq , int line_no , ID id , VALUE argc , const rb_iseq_t * blockiseq , VALUE flag , struct rb_call_info_kw_arg * keywords )
981
977
{
982
- VALUE * operands = (VALUE * )compile_data_alloc (iseq , sizeof (VALUE ) * 2 );
978
+ VALUE * operands = (VALUE * )compile_data_alloc (iseq , sizeof (VALUE ) * 3 );
983
979
operands [0 ] = (VALUE )new_callinfo (iseq , id , FIX2INT (argc ), FIX2INT (flag ), keywords , blockiseq != NULL );
984
- operands [1 ] = (VALUE )blockiseq ;
985
- return new_insn_core (iseq , line_no , BIN (send ), 2 , operands );
980
+ operands [1 ] = Qfalse ; /* cache */
981
+ operands [2 ] = (VALUE )blockiseq ;
982
+ return new_insn_core (iseq , line_no , BIN (send ), 3 , operands );
986
983
}
987
984
988
985
static rb_iseq_t *
@@ -1497,8 +1494,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
1497
1494
generated_iseq = ALLOC_N (VALUE , code_index );
1498
1495
line_info_table = ALLOC_N (struct iseq_line_info_entry , insn_num );
1499
1496
iseq -> body -> is_entries = ZALLOC_N (union iseq_inline_storage_entry , iseq -> body -> is_size );
1500
- iseq -> body -> callinfo_entries = ALLOC_N (rb_call_info_t , iseq -> body -> callinfo_size );
1501
- /* MEMZERO(iseq->body->callinfo_entries, rb_call_info_t, iseq->body->callinfo_size); */
1497
+ iseq -> body -> ci_entries = (struct rb_call_info * )ruby_xmalloc (sizeof (struct rb_call_info ) * iseq -> body -> ci_size +
1498
+ sizeof (struct rb_call_info_with_kwarg ) * iseq -> body -> ci_kw_size );
1499
+ iseq -> body -> cc_entries = ZALLOC_N (struct rb_call_cache , iseq -> body -> ci_size + iseq -> body -> ci_kw_size );
1500
+
1501
+ iseq -> compile_data -> ci_index = iseq -> compile_data -> ci_kw_index = 0 ;
1502
1502
1503
1503
list = FIRST_ELEMENT (anchor );
1504
1504
line_info_index = code_index = sp = 0 ;
@@ -1599,16 +1599,31 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
1599
1599
}
1600
1600
case TS_CALLINFO : /* call info */
1601
1601
{
1602
- rb_call_info_t * base_ci = (rb_call_info_t * )operands [j ];
1603
- rb_call_info_t * ci = & iseq -> body -> callinfo_entries [base_ci -> aux .index ];
1604
- * ci = * base_ci ;
1605
-
1606
- if (UNLIKELY (base_ci -> aux .index >= iseq -> body -> callinfo_size )) {
1607
- rb_bug ("iseq_set_sequence: ci_index overflow: index: %d, size: %d" , base_ci -> argc , iseq -> body -> callinfo_size );
1602
+ struct rb_call_info * base_ci = (struct rb_call_info * )operands [j ];
1603
+ struct rb_call_info * ci ;
1604
+
1605
+ if (base_ci -> flag & VM_CALL_KWARG ) {
1606
+ struct rb_call_info_with_kwarg * ci_kw_entries = (struct rb_call_info_with_kwarg * )& iseq -> body -> ci_entries [iseq -> body -> ci_size ];
1607
+ struct rb_call_info_with_kwarg * ci_kw = & ci_kw_entries [iseq -> compile_data -> ci_kw_index ++ ];
1608
+ * ci_kw = * ((struct rb_call_info_with_kwarg * )base_ci );
1609
+ ci = (struct rb_call_info * )ci_kw ;
1610
+ assert (iseq -> compile_data -> ci_kw_index <= iseq -> body -> ci_kw_size );
1611
+ }
1612
+ else {
1613
+ ci = & iseq -> body -> ci_entries [iseq -> compile_data -> ci_index ++ ];
1614
+ * ci = * base_ci ;
1615
+ assert (iseq -> compile_data -> ci_index <= iseq -> body -> ci_size );
1608
1616
}
1617
+
1609
1618
generated_iseq [code_index + 1 + j ] = (VALUE )ci ;
1610
1619
break ;
1611
1620
}
1621
+ case TS_CALLCACHE :
1622
+ {
1623
+ struct rb_call_cache * cc = & iseq -> body -> cc_entries [iseq -> compile_data -> ci_index + iseq -> compile_data -> ci_kw_index - 1 ];
1624
+ generated_iseq [code_index + 1 + j ] = (VALUE )cc ;
1625
+ break ;
1626
+ }
1612
1627
case TS_ID : /* ID */
1613
1628
generated_iseq [code_index + 1 + j ] = SYM2ID (operands [j ]);
1614
1629
break ;
@@ -1948,7 +1963,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
1948
1963
enum ruby_vminsn_type previ = piobj -> insn_id ;
1949
1964
1950
1965
if (previ == BIN (send ) || previ == BIN (opt_send_without_block ) || previ == BIN (invokesuper )) {
1951
- rb_call_info_t * ci = (rb_call_info_t * )piobj -> operands [0 ];
1966
+ struct rb_call_info * ci = (struct rb_call_info * )piobj -> operands [0 ];
1952
1967
rb_iseq_t * blockiseq = (rb_iseq_t * )piobj -> operands [1 ];
1953
1968
if (blockiseq == 0 ) {
1954
1969
ci -> flag |= VM_CALL_TAILCALL ;
@@ -1966,9 +1981,12 @@ insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
1966
1981
1967
1982
if (insn_id == BIN (opt_neq )) {
1968
1983
VALUE * old_operands = iobj -> operands ;
1984
+ iobj -> operand_size = 4 ;
1969
1985
iobj -> operands = (VALUE * )compile_data_alloc (iseq , iobj -> operand_size * sizeof (VALUE ));
1970
1986
iobj -> operands [0 ] = old_operands [0 ];
1971
- iobj -> operands [1 ] = (VALUE )new_callinfo (iseq , idEq , 1 , 0 , NULL , FALSE);
1987
+ iobj -> operands [1 ] = Qfalse ; /* CALL_CACHE */
1988
+ iobj -> operands [2 ] = (VALUE )new_callinfo (iseq , idEq , 1 , 0 , NULL , FALSE);
1989
+ iobj -> operands [3 ] = Qfalse ; /* CALL_CACHE */
1972
1990
}
1973
1991
1974
1992
return COMPILE_OK ;
@@ -1978,8 +1996,8 @@ static int
1978
1996
iseq_specialized_instruction (rb_iseq_t * iseq , INSN * iobj )
1979
1997
{
1980
1998
if (iobj -> insn_id == BIN (send )) {
1981
- rb_call_info_t * ci = (rb_call_info_t * )OPERAND_AT (iobj , 0 );
1982
- const rb_iseq_t * blockiseq = (rb_iseq_t * )OPERAND_AT (iobj , 1 );
1999
+ struct rb_call_info * ci = (struct rb_call_info * )OPERAND_AT (iobj , 0 );
2000
+ const rb_iseq_t * blockiseq = (rb_iseq_t * )OPERAND_AT (iobj , 2 );
1983
2001
1984
2002
#define SP_INSN (opt ) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
1985
2003
if (ci -> flag & VM_CALL_ARGS_SIMPLE ) {
@@ -2020,7 +2038,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
2020
2038
2021
2039
if ((ci -> flag & VM_CALL_ARGS_BLOCKARG ) == 0 && blockiseq == NULL ) {
2022
2040
iobj -> insn_id = BIN (opt_send_without_block );
2023
- iobj -> operand_size = 1 ;
2041
+ iobj -> operand_size = insn_len ( iobj -> insn_id ) - 1 ;
2024
2042
}
2025
2043
}
2026
2044
#undef SP_INSN
@@ -2402,7 +2420,7 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond,
2402
2420
}
2403
2421
2404
2422
static int
2405
- compile_array_keyword_arg (rb_iseq_t * iseq , LINK_ANCHOR * ret , const NODE * const root_node , rb_call_info_kw_arg_t * * const kw_arg_ptr )
2423
+ compile_array_keyword_arg (rb_iseq_t * iseq , LINK_ANCHOR * ret , const NODE * const root_node , struct rb_call_info_kw_arg * * const kw_arg_ptr )
2406
2424
{
2407
2425
if (kw_arg_ptr == NULL ) return FALSE;
2408
2426
@@ -2427,7 +2445,7 @@ compile_array_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE * const
2427
2445
node = root_node -> nd_head ;
2428
2446
{
2429
2447
int len = (int )node -> nd_alen / 2 ;
2430
- rb_call_info_kw_arg_t * kw_arg = (rb_call_info_kw_arg_t * )ruby_xmalloc (sizeof (rb_call_info_kw_arg_t ) + sizeof (VALUE ) * (len - 1 ));
2448
+ struct rb_call_info_kw_arg * kw_arg = (struct rb_call_info_kw_arg * )ruby_xmalloc (sizeof (struct rb_call_info_kw_arg ) + sizeof (VALUE ) * (len - 1 ));
2431
2449
VALUE * keywords = kw_arg -> keywords ;
2432
2450
int i = 0 ;
2433
2451
kw_arg -> keyword_len = len ;
@@ -2455,7 +2473,7 @@ enum compile_array_type_t {
2455
2473
2456
2474
static int
2457
2475
compile_array_ (rb_iseq_t * iseq , LINK_ANCHOR * ret , NODE * node_root ,
2458
- enum compile_array_type_t type , rb_call_info_kw_arg_t * * keywords_ptr , int poped )
2476
+ enum compile_array_type_t type , struct rb_call_info_kw_arg * * keywords_ptr , int poped )
2459
2477
{
2460
2478
NODE * node = node_root ;
2461
2479
int line = (int )nd_line (node );
@@ -2680,15 +2698,15 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
2680
2698
switch (nd_type (node )) {
2681
2699
case NODE_ATTRASGN : {
2682
2700
INSN * iobj ;
2683
- rb_call_info_t * ci ;
2701
+ struct rb_call_info * ci ;
2684
2702
VALUE dupidx ;
2685
2703
2686
2704
COMPILE_POPED (ret , "masgn lhs (NODE_ATTRASGN)" , node );
2687
2705
2688
2706
POP_ELEMENT (ret ); /* pop pop insn */
2689
2707
iobj = (INSN * )POP_ELEMENT (ret ); /* pop send insn */
2690
- ci = (rb_call_info_t * )iobj -> operands [0 ];
2691
- ci -> orig_argc += 1 ; ci -> argc = ci -> orig_argc ;
2708
+ ci = (struct rb_call_info * )iobj -> operands [0 ];
2709
+ ci -> orig_argc += 1 ;
2692
2710
dupidx = INT2FIX (ci -> orig_argc );
2693
2711
2694
2712
ADD_INSN1 (ret , nd_line (node ), topn , dupidx );
@@ -3228,7 +3246,7 @@ add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq, int is_return)
3228
3246
}
3229
3247
3230
3248
static VALUE
3231
- setup_args (rb_iseq_t * iseq , LINK_ANCHOR * args , NODE * argn , unsigned int * flag , rb_call_info_kw_arg_t * * keywords )
3249
+ setup_args (rb_iseq_t * iseq , LINK_ANCHOR * args , NODE * argn , unsigned int * flag , struct rb_call_info_kw_arg * * keywords )
3232
3250
{
3233
3251
VALUE argc = INT2FIX (0 );
3234
3252
int nsplat = 0 ;
@@ -4504,8 +4522,10 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
4504
4522
VALUE str = rb_fstring (node -> nd_args -> nd_head -> nd_lit );
4505
4523
node -> nd_args -> nd_head -> nd_lit = str ;
4506
4524
COMPILE (ret , "recv" , node -> nd_recv );
4507
- ADD_INSN2 (ret , line , opt_aref_with ,
4508
- new_callinfo (iseq , idAREF , 1 , 0 , NULL , FALSE), str );
4525
+ ADD_INSN3 (ret , line , opt_aref_with ,
4526
+ new_callinfo (iseq , idAREF , 1 , 0 , NULL , FALSE),
4527
+ Qnil , /* CALL_CACHE */
4528
+ str );
4509
4529
if (poped ) {
4510
4530
ADD_INSN (ret , line , pop );
4511
4531
}
@@ -4523,7 +4543,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
4523
4543
ID mid = node -> nd_mid ;
4524
4544
VALUE argc ;
4525
4545
unsigned int flag = 0 ;
4526
- rb_call_info_kw_arg_t * keywords = NULL ;
4546
+ struct rb_call_info_kw_arg * keywords = NULL ;
4527
4547
const rb_iseq_t * parent_block = iseq -> compile_data -> current_block ;
4528
4548
iseq -> compile_data -> current_block = NULL ;
4529
4549
@@ -4635,7 +4655,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
4635
4655
DECL_ANCHOR (args );
4636
4656
int argc ;
4637
4657
unsigned int flag = 0 ;
4638
- rb_call_info_kw_arg_t * keywords = NULL ;
4658
+ struct rb_call_info_kw_arg * keywords = NULL ;
4639
4659
const rb_iseq_t * parent_block = iseq -> compile_data -> current_block ;
4640
4660
4641
4661
INIT_ANCHOR (args );
@@ -4742,8 +4762,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
4742
4762
/* dummy receiver */
4743
4763
ADD_INSN1 (ret , line , putobject , nd_type (node ) == NODE_ZSUPER ? Qfalse : Qtrue );
4744
4764
ADD_SEQ (ret , args );
4745
- ADD_INSN2 (ret , line , invokesuper ,
4765
+ ADD_INSN3 (ret , line , invokesuper ,
4746
4766
new_callinfo (iseq , 0 , argc , flag | VM_CALL_SUPER | VM_CALL_FCALL , keywords , parent_block != NULL ),
4767
+ Qnil , /* CALL_CACHE */
4747
4768
parent_block );
4748
4769
4749
4770
if (poped ) {
@@ -4839,7 +4860,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
4839
4860
DECL_ANCHOR (args );
4840
4861
VALUE argc ;
4841
4862
unsigned int flag = 0 ;
4842
- rb_call_info_kw_arg_t * keywords = NULL ;
4863
+ struct rb_call_info_kw_arg * keywords = NULL ;
4843
4864
4844
4865
INIT_ANCHOR (args );
4845
4866
if (iseq -> body -> type == ISEQ_TYPE_TOP ) {
@@ -4982,7 +5003,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
4982
5003
else {
4983
5004
ADD_SEQ (ret , recv );
4984
5005
ADD_SEQ (ret , val );
4985
- ADD_INSN1 (ret , line , opt_regexpmatch2 , new_callinfo (iseq , idEqTilde , 1 , 0 , NULL , FALSE));
5006
+ ADD_INSN2 (ret , line , opt_regexpmatch2 , new_callinfo (iseq , idEqTilde , 1 , 0 , NULL , FALSE), Qnil );
4986
5007
}
4987
5008
}
4988
5009
else {
@@ -5516,8 +5537,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
5516
5537
ADD_INSN (ret , line , swap );
5517
5538
ADD_INSN1 (ret , line , topn , INT2FIX (1 ));
5518
5539
}
5519
- ADD_INSN2 (ret , line , opt_aset_with ,
5520
- new_callinfo (iseq , idASET , 2 , 0 , NULL , FALSE), str );
5540
+ ADD_INSN3 (ret , line , opt_aset_with ,
5541
+ new_callinfo (iseq , idASET , 2 , 0 , NULL , FALSE),
5542
+ Qnil /* CALL_CACHE */ , str );
5521
5543
ADD_INSN (ret , line , pop );
5522
5544
break ;
5523
5545
}
@@ -5687,13 +5709,17 @@ insn_data_to_s_detail(INSN *iobj)
5687
5709
break ;
5688
5710
case TS_CALLINFO : /* call info */
5689
5711
{
5690
- rb_call_info_t * ci = (rb_call_info_t * )OPERAND_AT (iobj , j );
5712
+ struct rb_call_info * ci = (struct rb_call_info * )OPERAND_AT (iobj , j );
5691
5713
rb_str_cat2 (str , "<callinfo:" );
5692
- if (ci -> mid )
5693
- rb_str_catf (str , "%" PRIsVALUE , rb_id2str (ci -> mid ));
5714
+ if (ci -> mid ) rb_str_catf (str , "%" PRIsVALUE , rb_id2str (ci -> mid ));
5694
5715
rb_str_catf (str , ", %d>" , ci -> orig_argc );
5695
5716
break ;
5696
5717
}
5718
+ case TS_CALLCACHE : /* call cache */
5719
+ {
5720
+ rb_str_catf (str , "<call cache>" );
5721
+ break ;
5722
+ }
5697
5723
case TS_CDHASH : /* case/when condition cache */
5698
5724
rb_str_cat2 (str , "<ch>" );
5699
5725
break ;
@@ -5911,7 +5937,7 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
5911
5937
ID mid = 0 ;
5912
5938
int orig_argc = 0 ;
5913
5939
unsigned int flag = 0 ;
5914
- rb_call_info_kw_arg_t * kw_arg = 0 ;
5940
+ struct rb_call_info_kw_arg * kw_arg = 0 ;
5915
5941
5916
5942
if (!NIL_P (op )) {
5917
5943
VALUE vmid = rb_hash_aref (op , ID2SYM (rb_intern ("mid" )));
@@ -6030,6 +6056,9 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
6030
6056
case TS_CALLINFO :
6031
6057
argv [j ] = iseq_build_callinfo_from_hash (iseq , op );
6032
6058
break ;
6059
+ case TS_CALLCACHE :
6060
+ argv [j ] = Qfalse ;
6061
+ break ;
6033
6062
case TS_ID :
6034
6063
argv [j ] = rb_convert_type (op , T_SYMBOL ,
6035
6064
"Symbol" , "to_sym" );
0 commit comments