@@ -1440,82 +1440,85 @@ gen_get_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt
1440
1440
struct rb_iv_index_tbl_entry * ent ;
1441
1441
struct st_table * iv_index_tbl = ROBJECT_IV_INDEX_TBL (comptime_receiver );
1442
1442
1443
- // Lookup index for the ivar the instruction loads
1444
- if (iv_index_tbl && rb_iv_index_tbl_lookup (iv_index_tbl , id , & ent )) {
1445
- uint32_t ivar_index = ent -> index ;
1443
+ // Make sure there is a mapping for this ivar in the index table
1444
+ if (!iv_index_tbl || !rb_iv_index_tbl_lookup (iv_index_tbl , id , & ent )) {
1445
+ rb_ivar_set (comptime_receiver , id , Qundef );
1446
+ iv_index_tbl = ROBJECT_IV_INDEX_TBL (comptime_receiver );
1447
+ RUBY_ASSERT (iv_index_tbl );
1448
+ // Redo the lookup
1449
+ RUBY_ASSERT_ALWAYS (rb_iv_index_tbl_lookup (iv_index_tbl , id , & ent ));
1450
+ }
1446
1451
1447
- // Pop receiver if it's on the temp stack
1448
- if (!reg0_opnd .is_self ) {
1449
- (void )ctx_stack_pop (ctx , 1 );
1450
- }
1452
+ uint32_t ivar_index = ent -> index ;
1451
1453
1452
- // Compile time self is embedded and the ivar index lands within the object
1453
- if (RB_FL_TEST_RAW (comptime_receiver , ROBJECT_EMBED ) && ivar_index < ROBJECT_EMBED_LEN_MAX ) {
1454
- // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h
1454
+ // Pop receiver if it's on the temp stack
1455
+ if (!reg0_opnd .is_self ) {
1456
+ (void )ctx_stack_pop (ctx , 1 );
1457
+ }
1455
1458
1456
- // Guard that self is embedded
1457
- // TODO: BT and JC is shorter
1458
- ADD_COMMENT (cb , "guard embedded getivar" );
1459
- x86opnd_t flags_opnd = member_opnd (REG0 , struct RBasic , flags );
1460
- test (cb , flags_opnd , imm_opnd (ROBJECT_EMBED ));
1461
- jit_chain_guard (JCC_JZ , jit , & starting_context , max_chain_depth , side_exit );
1459
+ // Compile time self is embedded and the ivar index lands within the object
1460
+ if (RB_FL_TEST_RAW (comptime_receiver , ROBJECT_EMBED ) && ivar_index < ROBJECT_EMBED_LEN_MAX ) {
1461
+ // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h
1462
1462
1463
- // Load the variable
1464
- x86opnd_t ivar_opnd = mem_opnd (64 , REG0 , offsetof(struct RObject , as .ary ) + ivar_index * SIZEOF_VALUE );
1465
- mov (cb , REG1 , ivar_opnd );
1463
+ // Guard that self is embedded
1464
+ // TODO: BT and JC is shorter
1465
+ ADD_COMMENT (cb , "guard embedded getivar" );
1466
+ x86opnd_t flags_opnd = member_opnd (REG0 , struct RBasic , flags );
1467
+ test (cb , flags_opnd , imm_opnd (ROBJECT_EMBED ));
1468
+ jit_chain_guard (JCC_JZ , jit , & starting_context , max_chain_depth , side_exit );
1466
1469
1467
- // Guard that the variable is not Qundef
1468
- cmp (cb , REG1 , imm_opnd (Qundef ));
1469
- mov (cb , REG0 , imm_opnd (Qnil ));
1470
- cmove (cb , REG1 , REG0 );
1470
+ // Load the variable
1471
+ x86opnd_t ivar_opnd = mem_opnd (64 , REG0 , offsetof(struct RObject , as .ary ) + ivar_index * SIZEOF_VALUE );
1472
+ mov (cb , REG1 , ivar_opnd );
1471
1473
1472
- // Push the ivar on the stack
1473
- x86opnd_t out_opnd = ctx_stack_push (ctx , TYPE_UNKNOWN );
1474
- mov (cb , out_opnd , REG1 );
1475
- }
1476
- else {
1477
- // Compile time value is *not* embeded.
1474
+ // Guard that the variable is not Qundef
1475
+ cmp (cb , REG1 , imm_opnd (Qundef ));
1476
+ mov (cb , REG0 , imm_opnd (Qnil ));
1477
+ cmove (cb , REG1 , REG0 );
1478
1478
1479
- // Guard that value is *not* embedded
1480
- // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h
1481
- ADD_COMMENT (cb , "guard extended getivar" );
1482
- x86opnd_t flags_opnd = member_opnd (REG0 , struct RBasic , flags );
1483
- test (cb , flags_opnd , imm_opnd (ROBJECT_EMBED ));
1484
- jit_chain_guard (JCC_JNZ , jit , & starting_context , max_chain_depth , side_exit );
1485
-
1486
- // check that the extended table is big enough
1487
- if (ivar_index >= ROBJECT_EMBED_LEN_MAX + 1 ) {
1488
- // Check that the slot is inside the extended table (num_slots > index)
1489
- x86opnd_t num_slots = mem_opnd (32 , REG0 , offsetof(struct RObject , as .heap .numiv ));
1490
- cmp (cb , num_slots , imm_opnd (ivar_index ));
1491
- jle_ptr (cb , COUNTED_EXIT (side_exit , getivar_idx_out_of_range ));
1492
- }
1479
+ // Push the ivar on the stack
1480
+ x86opnd_t out_opnd = ctx_stack_push (ctx , TYPE_UNKNOWN );
1481
+ mov (cb , out_opnd , REG1 );
1482
+ }
1483
+ else {
1484
+ // Compile time value is *not* embeded.
1493
1485
1494
- // Get a pointer to the extended table
1495
- x86opnd_t tbl_opnd = mem_opnd (64 , REG0 , offsetof(struct RObject , as .heap .ivptr ));
1496
- mov (cb , REG0 , tbl_opnd );
1486
+ // Guard that value is *not* embedded
1487
+ // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h
1488
+ ADD_COMMENT (cb , "guard extended getivar" );
1489
+ x86opnd_t flags_opnd = member_opnd (REG0 , struct RBasic , flags );
1490
+ test (cb , flags_opnd , imm_opnd (ROBJECT_EMBED ));
1491
+ jit_chain_guard (JCC_JNZ , jit , & starting_context , max_chain_depth , side_exit );
1492
+
1493
+ // check that the extended table is big enough
1494
+ if (ivar_index >= ROBJECT_EMBED_LEN_MAX + 1 ) {
1495
+ // Check that the slot is inside the extended table (num_slots > index)
1496
+ x86opnd_t num_slots = mem_opnd (32 , REG0 , offsetof(struct RObject , as .heap .numiv ));
1497
+ cmp (cb , num_slots , imm_opnd (ivar_index ));
1498
+ jle_ptr (cb , COUNTED_EXIT (side_exit , getivar_idx_out_of_range ));
1499
+ }
1497
1500
1498
- // Read the ivar from the extended table
1499
- x86opnd_t ivar_opnd = mem_opnd (64 , REG0 , sizeof ( VALUE ) * ivar_index );
1500
- mov (cb , REG0 , ivar_opnd );
1501
+ // Get a pointer to the extended table
1502
+ x86opnd_t tbl_opnd = mem_opnd (64 , REG0 , offsetof( struct RObject , as . heap . ivptr ) );
1503
+ mov (cb , REG0 , tbl_opnd );
1501
1504
1502
- // Check that the ivar is not Qundef
1503
- cmp (cb , REG0 , imm_opnd (Qundef ));
1504
- mov (cb , REG1 , imm_opnd (Qnil ));
1505
- cmove (cb , REG0 , REG1 );
1505
+ // Read the ivar from the extended table
1506
+ x86opnd_t ivar_opnd = mem_opnd (64 , REG0 , sizeof (VALUE ) * ivar_index );
1507
+ mov (cb , REG0 , ivar_opnd );
1506
1508
1507
- // Push the ivar on the stack
1508
- x86opnd_t out_opnd = ctx_stack_push ( ctx , TYPE_UNKNOWN );
1509
- mov (cb , out_opnd , REG0 );
1510
- }
1509
+ // Check that the ivar is not Qundef
1510
+ cmp ( cb , REG0 , imm_opnd ( Qundef ) );
1511
+ mov (cb , REG1 , imm_opnd ( Qnil ) );
1512
+ cmove ( cb , REG0 , REG1 );
1511
1513
1512
- // Jump to next instruction. This allows guard chains to share the same successor.
1513
- jit_jump_to_next_insn ( jit , ctx );
1514
- return YJIT_END_BLOCK ;
1514
+ // Push the ivar on the stack
1515
+ x86opnd_t out_opnd = ctx_stack_push ( ctx , TYPE_UNKNOWN );
1516
+ mov ( cb , out_opnd , REG0 ) ;
1515
1517
}
1516
1518
1517
- GEN_COUNTER_INC (cb , getivar_name_not_mapped );
1518
- return YJIT_CANT_COMPILE ;
1519
+ // Jump to next instruction. This allows guard chains to share the same successor.
1520
+ jit_jump_to_next_insn (jit , ctx );
1521
+ return YJIT_END_BLOCK ;
1519
1522
}
1520
1523
1521
1524
static codegen_status_t
0 commit comments