3438 __ null_check(r2, oopDesc::klass_offset_in_bytes()); |
3438 __ null_check(r2, oopDesc::klass_offset_in_bytes()); |
3439 __ load_klass(r3, r2); |
3439 __ load_klass(r3, r2); |
3440 |
3440 |
3441 Label no_such_interface, no_such_method; |
3441 Label no_such_interface, no_such_method; |
3442 |
3442 |
|
3443 // Preserve method for throw_AbstractMethodErrorVerbose. |
|
3444 __ mov(r16, rmethod); |
3443 // Receiver subtype check against REFC. |
3445 // Receiver subtype check against REFC. |
3444 // Superklass in r0. Subklass in r3. Blows rscratch2, r13 |
3446 // Superklass in r0. Subklass in r3. Blows rscratch2, r13 |
3445 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
3447 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
3446 r3, r0, noreg, |
3448 r3, r0, noreg, |
3447 // outputs: scan temp. reg, scan temp. reg |
3449 // outputs: scan temp. reg, scan temp. reg |
3458 __ ldr(r0, Address(r0, ConstantPool::pool_holder_offset_in_bytes())); |
3460 __ ldr(r0, Address(r0, ConstantPool::pool_holder_offset_in_bytes())); |
3459 __ ldrw(rmethod, Address(rmethod, Method::itable_index_offset())); |
3461 __ ldrw(rmethod, Address(rmethod, Method::itable_index_offset())); |
3460 __ subw(rmethod, rmethod, Method::itable_index_max); |
3462 __ subw(rmethod, rmethod, Method::itable_index_max); |
3461 __ negw(rmethod, rmethod); |
3463 __ negw(rmethod, rmethod); |
3462 |
3464 |
|
3465 // Preserve recvKlass for throw_AbstractMethodErrorVerbose. |
|
3466 __ mov(rlocals, r3); |
3463 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
3467 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
3464 r3, r0, rmethod, |
3468 rlocals, r0, rmethod, |
3465 // outputs: method, scan temp. reg |
3469 // outputs: method, scan temp. reg |
3466 rmethod, r13, |
3470 rmethod, r13, |
3467 no_such_interface); |
3471 no_such_interface); |
3468 |
3472 |
3469 // rmethod,: methodOop to call |
3473 // rmethod,: methodOop to call |
3488 |
3492 |
3489 __ bind(no_such_method); |
3493 __ bind(no_such_method); |
3490 // throw exception |
3494 // throw exception |
3491 __ restore_bcp(); // bcp must be correct for exception handler (was destroyed) |
3495 __ restore_bcp(); // bcp must be correct for exception handler (was destroyed) |
3492 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
3496 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
3493 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); |
3497 // Pass arguments for generating a verbose error message. |
|
3498 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorVerbose), r3, r16); |
3494 // the call_VM checks for exception, so we should never return here. |
3499 // the call_VM checks for exception, so we should never return here. |
3495 __ should_not_reach_here(); |
3500 __ should_not_reach_here(); |
3496 |
3501 |
3497 __ bind(no_such_interface); |
3502 __ bind(no_such_interface); |
3498 // throw exception |
3503 // throw exception |
3499 __ restore_bcp(); // bcp must be correct for exception handler (was destroyed) |
3504 __ restore_bcp(); // bcp must be correct for exception handler (was destroyed) |
3500 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
3505 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
|
3506 // Pass arguments for generating a verbose error message. |
3501 __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
3507 __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
3502 InterpreterRuntime::throw_IncompatibleClassChangeError)); |
3508 InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose), r3, r0); |
3503 // the call_VM checks for exception, so we should never return here. |
3509 // the call_VM checks for exception, so we should never return here. |
3504 __ should_not_reach_here(); |
3510 __ should_not_reach_here(); |
3505 return; |
3511 return; |
3506 } |
3512 } |
3507 |
3513 |