@@ -1196,6 +1196,110 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
1196
1196
}
1197
1197
}
1198
1198
1199
+ // Look up the method for a megamorphic invokeinterface call in a single pass over itable:
1200
+ // - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder
1201
+ // - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index
1202
+ // The target method is determined by <holder_klass, itable_index>.
1203
+ // The receiver klass is in recv_klass.
1204
+ // On success, the result will be in method_result, and execution falls through.
1205
+ // On failure, execution transfers to the given label.
1206
+ void MacroAssembler::lookup_interface_method_stub (Register recv_klass,
1207
+ Register holder_klass,
1208
+ Register resolved_klass,
1209
+ Register method_result,
1210
+ Register temp_itbl_klass,
1211
+ Register scan_temp,
1212
+ int itable_index,
1213
+ Label& L_no_such_interface) {
1214
+ // 'method_result' is only used as output register at the very end of this method.
1215
+ // Until then we can reuse it as 'holder_offset'.
1216
+ Register holder_offset = method_result;
1217
+ assert_different_registers (resolved_klass, recv_klass, holder_klass, temp_itbl_klass, scan_temp, holder_offset);
1218
+
1219
+ int vtable_start_offset = in_bytes (Klass::vtable_start_offset ());
1220
+ int itable_offset_entry_size = itableOffsetEntry::size () * wordSize;
1221
+ int ioffset = in_bytes (itableOffsetEntry::interface_offset ());
1222
+ int ooffset = in_bytes (itableOffsetEntry::offset_offset ());
1223
+
1224
+ Label L_loop_search_resolved_entry, L_resolved_found, L_holder_found;
1225
+
1226
+ ldrw (scan_temp, Address (recv_klass, Klass::vtable_length_offset ()));
1227
+ add (recv_klass, recv_klass, vtable_start_offset + ioffset);
1228
+ // itableOffsetEntry[] itable = recv_klass + Klass::vtable_start_offset() + sizeof(vtableEntry) * recv_klass->_vtable_len;
1229
+ // temp_itbl_klass = itable[0]._interface;
1230
+ int vtblEntrySize = vtableEntry::size_in_bytes ();
1231
+ assert (vtblEntrySize == wordSize, " ldr lsl shift amount must be 3" );
1232
+ ldr (temp_itbl_klass, Address (recv_klass, scan_temp, Address::lsl (exact_log2 (vtblEntrySize))));
1233
+ mov (holder_offset, zr);
1234
+ // scan_temp = &(itable[0]._interface)
1235
+ lea (scan_temp, Address (recv_klass, scan_temp, Address::lsl (exact_log2 (vtblEntrySize))));
1236
+
1237
+ // Initial checks:
1238
+ // - if (holder_klass != resolved_klass), go to "scan for resolved"
1239
+ // - if (itable[0] == holder_klass), shortcut to "holder found"
1240
+ // - if (itable[0] == 0), no such interface
1241
+ cmp (resolved_klass, holder_klass);
1242
+ br (Assembler::NE, L_loop_search_resolved_entry);
1243
+ cmp (holder_klass, temp_itbl_klass);
1244
+ br (Assembler::EQ, L_holder_found);
1245
+ cbz (temp_itbl_klass, L_no_such_interface);
1246
+
1247
+ // Loop: Look for holder_klass record in itable
1248
+ // do {
1249
+ // temp_itbl_klass = *(scan_temp += itable_offset_entry_size);
1250
+ // if (temp_itbl_klass == holder_klass) {
1251
+ // goto L_holder_found; // Found!
1252
+ // }
1253
+ // } while (temp_itbl_klass != 0);
1254
+ // goto L_no_such_interface // Not found.
1255
+ Label L_search_holder;
1256
+ bind (L_search_holder);
1257
+ ldr (temp_itbl_klass, Address (pre (scan_temp, itable_offset_entry_size)));
1258
+ cmp (holder_klass, temp_itbl_klass);
1259
+ br (Assembler::EQ, L_holder_found);
1260
+ cbnz (temp_itbl_klass, L_search_holder);
1261
+
1262
+ b (L_no_such_interface);
1263
+
1264
+ // Loop: Look for resolved_class record in itable
1265
+ // while (true) {
1266
+ // temp_itbl_klass = *(scan_temp += itable_offset_entry_size);
1267
+ // if (temp_itbl_klass == 0) {
1268
+ // goto L_no_such_interface;
1269
+ // }
1270
+ // if (temp_itbl_klass == resolved_klass) {
1271
+ // goto L_resolved_found; // Found!
1272
+ // }
1273
+ // if (temp_itbl_klass == holder_klass) {
1274
+ // holder_offset = scan_temp;
1275
+ // }
1276
+ // }
1277
+ //
1278
+ Label L_loop_search_resolved;
1279
+ bind (L_loop_search_resolved);
1280
+ ldr (temp_itbl_klass, Address (pre (scan_temp, itable_offset_entry_size)));
1281
+ bind (L_loop_search_resolved_entry);
1282
+ cbz (temp_itbl_klass, L_no_such_interface);
1283
+ cmp (resolved_klass, temp_itbl_klass);
1284
+ br (Assembler::EQ, L_resolved_found);
1285
+ cmp (holder_klass, temp_itbl_klass);
1286
+ br (Assembler::NE, L_loop_search_resolved);
1287
+ mov (holder_offset, scan_temp);
1288
+ b (L_loop_search_resolved);
1289
+
1290
+ // See if we already have a holder klass. If not, go and scan for it.
1291
+ bind (L_resolved_found);
1292
+ cbz (holder_offset, L_search_holder);
1293
+ mov (scan_temp, holder_offset);
1294
+
1295
+ // Finally, scan_temp contains holder_klass vtable offset
1296
+ bind (L_holder_found);
1297
+ ldrw (method_result, Address (scan_temp, ooffset - ioffset));
1298
+ add (recv_klass, recv_klass, itable_index * wordSize + in_bytes (itableMethodEntry::method_offset ())
1299
+ - vtable_start_offset - ioffset); // substract offsets to restore the original value of recv_klass
1300
+ ldr (method_result, Address (recv_klass, method_result, Address::uxtw (0 )));
1301
+ }
1302
+
1199
1303
// virtual method calling
1200
1304
void MacroAssembler::lookup_virtual_method (Register recv_klass,
1201
1305
RegisterOrConstant vtable_index,
0 commit comments