@@ -3611,6 +3611,278 @@ void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass,
36113611 bind (L_fallthrough);
36123612}
36133613
3614+ // population_count variant for running without the CPOP
3615+ // instruction, which was introduced with Zbb extension.
3616+ void MacroAssembler::population_count (Register dst, Register src,
3617+ Register tmp1, Register tmp2) {
3618+ if (UsePopCountInstruction) {
3619+ cpop (dst, src);
3620+ } else {
3621+ assert_different_registers (src, tmp1, tmp2);
3622+ assert_different_registers (dst, tmp1, tmp2);
3623+ Label loop, done;
3624+
3625+ mv (tmp1, src);
3626+ // dst = 0;
3627+ // while(tmp1 != 0) {
3628+ // dst++;
3629+ // tmp1 &= (tmp1 - 1);
3630+ // }
3631+ mv (dst, zr);
3632+ beqz (tmp1, done);
3633+ {
3634+ bind (loop);
3635+ addi (dst, dst, 1 );
3636+ addi (tmp2, tmp1, -1 );
3637+ andr (tmp1, tmp1, tmp2);
3638+ bnez (tmp1, loop);
3639+ }
3640+ bind (done);
3641+ }
3642+ }
3643+
3644+ // Ensure that the inline code and the stub are using the same registers
3645+ // as we need to call the stub from inline code when there is a collision
3646+ // in the hashed lookup in the secondary supers array.
3647+ #define LOOKUP_SECONDARY_SUPERS_TABLE_REGISTERS (r_super_klass, r_array_base, r_array_length, \
3648+ r_array_index, r_sub_klass, result, r_bitmap) \
3649+ do { \
3650+ assert (r_super_klass == x10 && \
3651+ r_array_base == x11 && \
3652+ r_array_length == x12 && \
3653+ (r_array_index == x13 || r_array_index == noreg) && \
3654+ (r_sub_klass == x14 || r_sub_klass == noreg) && \
3655+ (result == x15 || result == noreg) && \
3656+ (r_bitmap == x16 || r_bitmap == noreg), " registers must match riscv.ad" ); \
3657+ } while (0 )
3658+
3659+ // Return true: we succeeded in generating this code
3660+ bool MacroAssembler::lookup_secondary_supers_table (Register r_sub_klass,
3661+ Register r_super_klass,
3662+ Register result,
3663+ Register tmp1,
3664+ Register tmp2,
3665+ Register tmp3,
3666+ Register tmp4,
3667+ u1 super_klass_slot,
3668+ bool stub_is_near) {
3669+ assert_different_registers (r_sub_klass, r_super_klass, result, tmp1, tmp2, tmp3, tmp4, t0);
3670+
3671+ Label L_fallthrough;
3672+
3673+ BLOCK_COMMENT (" lookup_secondary_supers_table {" );
3674+
3675+ const Register
3676+ r_array_base = tmp1, // x11
3677+ r_array_length = tmp2, // x12
3678+ r_array_index = tmp3, // x13
3679+ r_bitmap = tmp4; // x16
3680+
3681+ LOOKUP_SECONDARY_SUPERS_TABLE_REGISTERS (r_super_klass, r_array_base, r_array_length,
3682+ r_array_index, r_sub_klass, result, r_bitmap);
3683+
3684+ u1 bit = super_klass_slot;
3685+
3686+ // Initialize result value to 1 which means mismatch.
3687+ mv (result, 1 );
3688+
3689+ ld (r_bitmap, Address (r_sub_klass, Klass::bitmap_offset ()));
3690+
3691+ // First check the bitmap to see if super_klass might be present. If
3692+ // the bit is zero, we are certain that super_klass is not one of
3693+ // the secondary supers.
3694+ test_bit (t0, r_bitmap, bit);
3695+ beqz (t0, L_fallthrough);
3696+
3697+ // Get the first array index that can contain super_klass into r_array_index.
3698+ if (bit != 0 ) {
3699+ slli (r_array_index, r_bitmap, (Klass::SECONDARY_SUPERS_TABLE_MASK - bit));
3700+ population_count (r_array_index, r_array_index, tmp1, tmp2);
3701+ } else {
3702+ mv (r_array_index, (u1)1 );
3703+ }
3704+
3705+ // We will consult the secondary-super array.
3706+ ld (r_array_base, Address (r_sub_klass, in_bytes (Klass::secondary_supers_offset ())));
3707+
3708+ // The value i in r_array_index is >= 1, so even though r_array_base
3709+ // points to the length, we don't need to adjust it to point to the data.
3710+ assert (Array<Klass*>::base_offset_in_bytes () == wordSize, " Adjust this code" );
3711+ assert (Array<Klass*>::length_offset_in_bytes () == 0 , " Adjust this code" );
3712+
3713+ shadd (result, r_array_index, r_array_base, result, LogBytesPerWord);
3714+ ld (result, Address (result));
3715+ xorr (result, result, r_super_klass);
3716+ beqz (result, L_fallthrough); // Found a match
3717+
3718+ // Is there another entry to check? Consult the bitmap.
3719+ test_bit (t0, r_bitmap, (bit + 1 ) & Klass::SECONDARY_SUPERS_TABLE_MASK);
3720+ beqz (t0, L_fallthrough);
3721+
3722+ // Linear probe.
3723+ if (bit != 0 ) {
3724+ ror_imm (r_bitmap, r_bitmap, bit);
3725+ }
3726+
3727+ // The slot we just inspected is at secondary_supers[r_array_index - 1].
3728+ // The next slot to be inspected, by the stub we're about to call,
3729+ // is secondary_supers[r_array_index]. Bits 0 and 1 in the bitmap
3730+ // have been checked.
3731+ Address stub = RuntimeAddress (StubRoutines::lookup_secondary_supers_table_slow_path_stub ());
3732+ if (stub_is_near) {
3733+ jump_link (stub, t0);
3734+ } else {
3735+ address call = trampoline_call (stub);
3736+ if (call == nullptr ) {
3737+ return false ; // trampoline allocation failed
3738+ }
3739+ }
3740+
3741+ BLOCK_COMMENT (" } lookup_secondary_supers_table" );
3742+
3743+ bind (L_fallthrough);
3744+
3745+ if (VerifySecondarySupers) {
3746+ verify_secondary_supers_table (r_sub_klass, r_super_klass, // x14, x10
3747+ result, tmp1, tmp2, tmp3); // x15, x11, x12, x13
3748+ }
3749+ return true ;
3750+ }
3751+
3752+ // Called by code generated by check_klass_subtype_slow_path
3753+ // above. This is called when there is a collision in the hashed
3754+ // lookup in the secondary supers array.
3755+ void MacroAssembler::lookup_secondary_supers_table_slow_path (Register r_super_klass,
3756+ Register r_array_base,
3757+ Register r_array_index,
3758+ Register r_bitmap,
3759+ Register result,
3760+ Register tmp1) {
3761+ assert_different_registers (r_super_klass, r_array_base, r_array_index, r_bitmap, tmp1, result, t0);
3762+
3763+ const Register
3764+ r_array_length = tmp1,
3765+ r_sub_klass = noreg; // unused
3766+
3767+ LOOKUP_SECONDARY_SUPERS_TABLE_REGISTERS (r_super_klass, r_array_base, r_array_length,
3768+ r_array_index, r_sub_klass, result, r_bitmap);
3769+
3770+ Label L_matched, L_fallthrough, L_bitmap_full;
3771+
3772+ // Initialize result value to 1 which means mismatch.
3773+ mv (result, 1 );
3774+
3775+ // Load the array length.
3776+ lwu (r_array_length, Address (r_array_base, Array<Klass*>::length_offset_in_bytes ()));
3777+ // And adjust the array base to point to the data.
3778+ // NB! Effectively increments current slot index by 1.
3779+ assert (Array<Klass*>::base_offset_in_bytes () == wordSize, " " );
3780+ addi (r_array_base, r_array_base, Array<Klass*>::base_offset_in_bytes ());
3781+
3782+ // Check if bitmap is SECONDARY_SUPERS_BITMAP_FULL
3783+ assert (Klass::SECONDARY_SUPERS_BITMAP_FULL == ~uintx (0 ), " Adjust this code" );
3784+ addi (t0, r_bitmap, (u1)1 );
3785+ beqz (t0, L_bitmap_full);
3786+
3787+ // NB! Our caller has checked bits 0 and 1 in the bitmap. The
3788+ // current slot (at secondary_supers[r_array_index]) has not yet
3789+ // been inspected, and r_array_index may be out of bounds if we
3790+ // wrapped around the end of the array.
3791+
3792+ { // This is conventional linear probing, but instead of terminating
3793+ // when a null entry is found in the table, we maintain a bitmap
3794+ // in which a 0 indicates missing entries.
3795+ // The check above guarantees there are 0s in the bitmap, so the loop
3796+ // eventually terminates.
3797+ Label L_loop;
3798+ bind (L_loop);
3799+
3800+ // Check for wraparound.
3801+ Label skip;
3802+ bge (r_array_length, r_array_index, skip);
3803+ mv (r_array_index, zr);
3804+ bind (skip);
3805+
3806+ shadd (t0, r_array_index, r_array_base, t0, LogBytesPerWord);
3807+ ld (t0, Address (t0));
3808+ beq (t0, r_super_klass, L_matched);
3809+
3810+ test_bit (t0, r_bitmap, 2 ); // look-ahead check (Bit 2); result is non-zero
3811+ beqz (t0, L_fallthrough);
3812+
3813+ ror_imm (r_bitmap, r_bitmap, 1 );
3814+ addi (r_array_index, r_array_index, 1 );
3815+ j (L_loop);
3816+ }
3817+
3818+ { // Degenerate case: more than 64 secondary supers.
3819+ // FIXME: We could do something smarter here, maybe a vectorized
3820+ // comparison or a binary search, but is that worth any added
3821+ // complexity?
3822+ bind (L_bitmap_full);
3823+ repne_scan (r_array_base, r_super_klass, r_array_length, t0);
3824+ bne (r_super_klass, t0, L_fallthrough);
3825+ }
3826+
3827+ bind (L_matched);
3828+ mv (result, zr);
3829+
3830+ bind (L_fallthrough);
3831+ }
3832+
3833+ // Make sure that the hashed lookup and a linear scan agree.
3834+ void MacroAssembler::verify_secondary_supers_table (Register r_sub_klass,
3835+ Register r_super_klass,
3836+ Register result,
3837+ Register tmp1,
3838+ Register tmp2,
3839+ Register tmp3) {
3840+ assert_different_registers (r_sub_klass, r_super_klass, tmp1, tmp2, tmp3, result, t0);
3841+
3842+ const Register
3843+ r_array_base = tmp1, // X11
3844+ r_array_length = tmp2, // X12
3845+ r_array_index = noreg, // unused
3846+ r_bitmap = noreg; // unused
3847+
3848+ LOOKUP_SECONDARY_SUPERS_TABLE_REGISTERS (r_super_klass, r_array_base, r_array_length,
3849+ r_array_index, r_sub_klass, result, r_bitmap);
3850+
3851+ BLOCK_COMMENT (" verify_secondary_supers_table {" );
3852+
3853+ // We will consult the secondary-super array.
3854+ ld (r_array_base, Address (r_sub_klass, in_bytes (Klass::secondary_supers_offset ())));
3855+
3856+ // Load the array length.
3857+ lwu (r_array_length, Address (r_array_base, Array<Klass*>::length_offset_in_bytes ()));
3858+ // And adjust the array base to point to the data.
3859+ addi (r_array_base, r_array_base, Array<Klass*>::base_offset_in_bytes ());
3860+
3861+ repne_scan (r_array_base, r_super_klass, r_array_length, t0);
3862+ Label failed;
3863+ mv (tmp3, 1 );
3864+ bne (r_super_klass, t0, failed);
3865+ mv (tmp3, zr);
3866+ bind (failed);
3867+
3868+ snez (result, result); // normalize result to 0/1 for comparison
3869+
3870+ Label passed;
3871+ beq (tmp3, result, passed);
3872+ {
3873+ mv (x10, r_super_klass);
3874+ mv (x11, r_sub_klass);
3875+ mv (x12, tmp3);
3876+ mv (x13, result);
3877+ mv (x14, (address)(" mismatch" ));
3878+ rt_call (CAST_FROM_FN_PTR (address, Klass::on_secondary_supers_verification_failure));
3879+ should_not_reach_here ();
3880+ }
3881+ bind (passed);
3882+
3883+ BLOCK_COMMENT (" } verify_secondary_supers_table" );
3884+ }
3885+
36143886// Defines obj, preserves var_size_in_bytes, okay for tmp2 == var_size_in_bytes.
36153887void MacroAssembler::tlab_allocate (Register obj,
36163888 Register var_size_in_bytes,
0 commit comments