--- old/src/hotspot/cpu/x86/templateTable_x86.cpp 2018-05-04 00:46:53.015416468 -0400 +++ new/src/hotspot/cpu/x86/templateTable_x86.cpp 2018-05-04 00:46:51.479327381 -0400 @@ -3791,15 +3791,29 @@ // rcx: receiver // rdx: flags + Label no_such_interface; // for receiver subtype check + Register recvKlass; // used for exception processing + // Check for private method invocation - indicated by vfinal Label notVFinal; __ movl(rlocals, rdx); __ andl(rlocals, (1 << ConstantPoolCacheEntry::is_vfinal_shift)); __ jcc(Assembler::zero, notVFinal); - // do the call - rbx is actually the method to call + // Get receiver klass into rlocals - also a null check + __ null_check(rcx, oopDesc::klass_offset_in_bytes()); + __ load_klass(rlocals, rcx); - __ null_check(rcx); + Label subtype; + __ check_klass_subtype(rlocals, rax, rbcp, subtype); + // If we get here the typecheck failed + recvKlass = rdx; + __ mov(recvKlass, rlocals); // shuffle receiver class for exception use + __ jmp(no_such_interface); + + __ bind(subtype); + + // do the call - rbx is actually the method to call __ profile_final_call(rdx); __ profile_arguments_type(rdx, rbx, rbcp, true); @@ -3826,7 +3840,7 @@ __ null_check(rcx, oopDesc::klass_offset_in_bytes()); __ load_klass(rdx, rcx); - Label no_such_interface, no_such_method; + Label no_such_method; // Preserve method for throw_AbstractMethodErrorVerbose. __ mov(rcx, rbx); @@ -3888,12 +3902,12 @@ __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) // Pass arguments for generating a verbose error message. #ifdef _LP64 - Register recvKlass = c_rarg1; + recvKlass = c_rarg1; Register method = c_rarg2; if (recvKlass != rdx) { __ movq(recvKlass, rdx); } if (method != rcx) { __ movq(method, rcx); } #else - Register recvKlass = rdx; + recvKlass = rdx; Register method = rcx; #endif __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorVerbose),