@@ -1035,6 +1035,88 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
10351035 }
10361036}
10371037
1038+ void MacroAssembler::lookup_interface_method_in_stub (Register recv_klass,
1039+ Register resolved_klass,
1040+ Register holder_klass,
1041+ int itable_index,
1042+ Register method_result,
1043+ Register scan_temp,
1044+ Register count,
1045+ Label& L_no_such_interface
1046+ ) {
1047+ assert_different_registers (recv_klass, resolved_klass, holder_klass);
1048+ assert_different_registers (method_result, scan_temp, count);
1049+
1050+ // Compute start of first itableOffsetEntry (which is at the end of the vtable)
1051+ int vtable_base = in_bytes (Klass::vtable_start_offset ());
1052+ int itentry_off = itableMethodEntry::method_offset_in_bytes ();
1053+ int scan_step = itableOffsetEntry::size () * wordSize;
1054+ int vte_size = vtableEntry::size_in_bytes ();
1055+ assert (vte_size == wordSize, " else adjust times_vte_scale" );
1056+
1057+ ldrw (scan_temp, Address (recv_klass, Klass::vtable_length_offset ()));
1058+
1059+ // %%% Could store the aligned, prescaled offset in the klassoop.
1060+ lea (scan_temp, Address (recv_klass, scan_temp, Address::lsl (3 )));
1061+ add (scan_temp, scan_temp, vtable_base);
1062+ mov (count, -2 );
1063+
1064+ // Adjust recv_klass by scaled itable_index, so we can free itable_index.
1065+ assert (itableMethodEntry::size () * wordSize == wordSize, " adjust the scaling in the code below" );
1066+ if (itable_index != 0 ) {
1067+ lea (recv_klass, Address (recv_klass, itable_index, Address::lsl (3 )));
1068+ }
1069+ if (itentry_off) {
1070+ add (recv_klass, recv_klass, itentry_off);
1071+ }
1072+
1073+ Label L_fast_loop, L_slow_loop, L_slow_loop_tail, L_exit;
1074+
1075+ cmp (holder_klass, resolved_klass);
1076+ br (Assembler::NE, L_slow_loop);
1077+
1078+ // fast loop, check holder klass only
1079+ bind (L_fast_loop);
1080+ if (itableOffsetEntry::interface_offset_in_bytes () == 0 ) {
1081+ ldr (method_result, Address (post (scan_temp, scan_step)));
1082+ } else {
1083+ ldr (method_result, Address (scan_temp, itableOffsetEntry::interface_offset_in_bytes ()));
1084+ add (scan_temp, scan_temp, scan_step);
1085+ }
1086+ cbz (method_result, L_no_such_interface);
1087+ // check holder_klass
1088+ cmp (holder_klass, method_result);
1089+ br (Assembler::NE, L_fast_loop);
1090+ // found, holder_klass can be free for other use
1091+ ldrw (holder_klass, Address (scan_temp, -scan_step + itableOffsetEntry::offset_offset_in_bytes ()));
1092+ b (L_exit);
1093+
1094+ // slow loop, search both resolved_klass and holder_klass
1095+ bind (L_slow_loop);
1096+ if (itableOffsetEntry::interface_offset_in_bytes () == 0 ) {
1097+ ldr (method_result, Address (post (scan_temp, scan_step)));
1098+ } else {
1099+ ldr (method_result, Address (scan_temp, itableOffsetEntry::interface_offset_in_bytes ()));
1100+ add (scan_temp, scan_temp, scan_step);
1101+ }
1102+ cbz (method_result, L_no_such_interface);
1103+ // check resolved_klass
1104+ cmp (resolved_klass, method_result);
1105+ csinc (count, count, count, Assembler::NE);
1106+ // check holder_klass
1107+ cmp (holder_klass, method_result);
1108+ br (Assembler::NE, L_slow_loop_tail);
1109+ increment (count);
1110+ // holder_klass can be free for other use
1111+ ldrw (holder_klass, Address (scan_temp, -scan_step + itableOffsetEntry::offset_offset_in_bytes ()));
1112+ bind (L_slow_loop_tail);
1113+ cbnz (count, L_slow_loop);
1114+
1115+ // Got a hit.
1116+ bind (L_exit);
1117+ ldr (method_result, Address (recv_klass, holder_klass, Address::uxtw (0 )));
1118+ }
1119+
10381120// virtual method calling
10391121void MacroAssembler::lookup_virtual_method (Register recv_klass,
10401122 RegisterOrConstant vtable_index,
0 commit comments