Fri, 29 Sep 2017 14:30:05 -0400
8174962: Better interface invocations
Reviewed-by: jrose, coleenp, ahgross, acorn, vlivanov
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java Tue Aug 08 12:02:01 2017 +0100 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java Fri Sep 29 14:30:05 2017 -0400 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -40,10 +40,10 @@ 1.11 } 1.12 1.13 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 1.14 - Type type = db.lookupType("CompiledICHolder"); 1.15 - holderMethod = new MetadataField(type.getAddressField("_holder_method"), 0); 1.16 - holderKlass = new MetadataField(type.getAddressField("_holder_klass"), 0); 1.17 - headerSize = type.getSize(); 1.18 + Type type = db.lookupType("CompiledICHolder"); 1.19 + holderMetadata = new MetadataField(type.getAddressField("_holder_metadata"), 0); 1.20 + holderKlass = new MetadataField(type.getAddressField("_holder_klass"), 0); 1.21 + headerSize = type.getSize(); 1.22 } 1.23 1.24 public CompiledICHolder(Address addr) { 1.25 @@ -55,12 +55,12 @@ 1.26 private static long headerSize; 1.27 1.28 // Fields 1.29 - private static MetadataField holderMethod; 1.30 + private static MetadataField holderMetadata; 1.31 private static MetadataField holderKlass; 1.32 1.33 // Accessors for declared fields 1.34 - public Method getHolderMethod() { return (Method) holderMethod.getValue(this); } 1.35 - public Klass getHolderKlass() { return (Klass) holderKlass.getValue(this); } 1.36 + public Metadata getHolderMetadata() { return (Metadata) holderMetadata.getValue(this); } 1.37 + public Klass getHolderKlass() { return (Klass) holderKlass.getValue(this); } 1.38 1.39 public void printValueOn(PrintStream tty) { 1.40 tty.print("CompiledICHolder");
2.1 --- a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Tue Aug 08 12:02:01 2017 +0100 2.2 +++ b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Fri Sep 29 14:30:05 2017 -0400 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 2.7 * Copyright 2012, 2014 SAP AG. All rights reserved. 2.8 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.9 * 2.10 @@ -1193,7 +1193,7 @@ 2.11 // Argument is valid and klass is as expected, continue. 2.12 2.13 // Extract method from inline cache, verified entry point needs it. 2.14 - __ ld(R19_method, CompiledICHolder::holder_method_offset(), ic); 2.15 + __ ld(R19_method, CompiledICHolder::holder_metadata_offset(), ic); 2.16 assert(R19_method == ic, "the inline cache register is dead here"); 2.17 2.18 __ ld(code, method_(code));
3.1 --- a/src/cpu/sparc/vm/macroAssembler_sparc.cpp Tue Aug 08 12:02:01 2017 +0100 3.2 +++ b/src/cpu/sparc/vm/macroAssembler_sparc.cpp Fri Sep 29 14:30:05 2017 -0400 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -2183,9 +2183,10 @@ 3.11 Register method_result, 3.12 Register scan_temp, 3.13 Register sethi_temp, 3.14 - Label& L_no_such_interface) { 3.15 + Label& L_no_such_interface, 3.16 + bool return_method) { 3.17 assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); 3.18 - assert(itable_index.is_constant() || itable_index.as_register() == method_result, 3.19 + assert(!return_method || itable_index.is_constant() || itable_index.as_register() == method_result, 3.20 "caller must use same register for non-constant itable index as for method"); 3.21 3.22 Label L_no_such_interface_restore; 3.23 @@ -2229,11 +2230,13 @@ 3.24 } 3.25 add(recv_klass, scan_temp, scan_temp); 3.26 3.27 - // Adjust recv_klass by scaled itable_index, so we can free itable_index. 3.28 - RegisterOrConstant itable_offset = itable_index; 3.29 - itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); 3.30 - itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); 3.31 - add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); 3.32 + if (return_method) { 3.33 + // Adjust recv_klass by scaled itable_index, so we can free itable_index. 3.34 + RegisterOrConstant itable_offset = itable_index; 3.35 + itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); 3.36 + itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); 3.37 + add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); 3.38 + } 3.39 3.40 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { 3.41 // if (scan->interface() == intf) { 3.42 @@ -2268,12 +2271,14 @@ 3.43 3.44 bind(L_found_method); 3.45 3.46 - // Got a hit. 3.47 - int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); 3.48 - // scan_temp[-scan_step] points to the vtable offset we need 3.49 - ito_offset -= scan_step; 3.50 - lduw(scan_temp, ito_offset, scan_temp); 3.51 - ld_ptr(recv_klass, scan_temp, method_result); 3.52 + if (return_method) { 3.53 + // Got a hit. 3.54 + int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); 3.55 + // scan_temp[-scan_step] points to the vtable offset we need 3.56 + ito_offset -= scan_step; 3.57 + lduw(scan_temp, ito_offset, scan_temp); 3.58 + ld_ptr(recv_klass, scan_temp, method_result); 3.59 + } 3.60 3.61 if (did_save) { 3.62 Label L_done;
4.1 --- a/src/cpu/sparc/vm/macroAssembler_sparc.hpp Tue Aug 08 12:02:01 2017 +0100 4.2 +++ b/src/cpu/sparc/vm/macroAssembler_sparc.hpp Fri Sep 29 14:30:05 2017 -0400 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 4.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 4.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 * 4.9 * This code is free software; you can redistribute it and/or modify it 4.10 @@ -1347,7 +1347,8 @@ 4.11 RegisterOrConstant itable_index, 4.12 Register method_result, 4.13 Register temp_reg, Register temp2_reg, 4.14 - Label& no_such_interface); 4.15 + Label& no_such_interface, 4.16 + bool return_method = true); 4.17 4.18 // virtual method calling 4.19 void lookup_virtual_method(Register recv_klass,
5.1 --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Tue Aug 08 12:02:01 2017 +0100 5.2 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Sep 29 14:30:05 2017 -0400 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -1045,7 +1045,7 @@ 5.11 5.12 Label ok, ok2; 5.13 __ brx(Assembler::equal, false, Assembler::pt, ok); 5.14 - __ delayed()->ld_ptr(G5_method, CompiledICHolder::holder_method_offset(), G5_method); 5.15 + __ delayed()->ld_ptr(G5_method, CompiledICHolder::holder_metadata_offset(), G5_method); 5.16 __ jump_to(ic_miss, G3_scratch); 5.17 __ delayed()->nop(); 5.18
6.1 --- a/src/cpu/sparc/vm/templateTable_sparc.cpp Tue Aug 08 12:02:01 2017 +0100 6.2 +++ b/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Sep 29 14:30:05 2017 -0400 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 6.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -3165,15 +3165,15 @@ 6.11 assert(byte_no == f1_byte, "use this argument"); 6.12 6.13 const Register Rinterface = G1_scratch; 6.14 + const Register Rmethod = Lscratch; 6.15 const Register Rret = G3_scratch; 6.16 - const Register Rindex = Lscratch; 6.17 const Register O0_recv = O0; 6.18 const Register O1_flags = O1; 6.19 const Register O2_Klass = O2; 6.20 const Register Rscratch = G4_scratch; 6.21 assert_different_registers(Rscratch, G5_method); 6.22 6.23 - prepare_invoke(byte_no, Rinterface, Rret, Rindex, O0_recv, O1_flags); 6.24 + prepare_invoke(byte_no, Rinterface, Rret, Rmethod, O0_recv, O1_flags); 6.25 6.26 // get receiver klass 6.27 __ null_check(O0_recv, oopDesc::klass_offset_in_bytes()); 6.28 @@ -3193,58 +3193,40 @@ 6.29 6.30 __ bind(notMethod); 6.31 6.32 + Register Rtemp = O1_flags; 6.33 + 6.34 + Label L_no_such_interface; 6.35 + 6.36 + // Receiver subtype check against REFC. 6.37 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 6.38 + O2_Klass, Rinterface, noreg, 6.39 + // outputs: temp reg1, temp reg2, temp reg3 6.40 + G5_method, Rscratch, Rtemp, 6.41 + L_no_such_interface, 6.42 + /*return_method=*/false); 6.43 + 6.44 __ profile_virtual_call(O2_Klass, O4); 6.45 6.46 // 6.47 // find entry point to call 6.48 // 6.49 6.50 - // compute start of first itableOffsetEntry (which is at end of vtable) 6.51 - const int base = InstanceKlass::vtable_start_offset() * wordSize; 6.52 - Label search; 6.53 - Register Rtemp = O1_flags; 6.54 - 6.55 - __ ld(O2_Klass, InstanceKlass::vtable_length_offset() * wordSize, Rtemp); 6.56 - if (align_object_offset(1) > 1) { 6.57 - __ round_to(Rtemp, align_object_offset(1)); 6.58 - } 6.59 - __ sll(Rtemp, LogBytesPerWord, Rtemp); // Rscratch *= 4; 6.60 - if (Assembler::is_simm13(base)) { 6.61 - __ add(Rtemp, base, Rtemp); 6.62 - } else { 6.63 - __ set(base, Rscratch); 6.64 - __ add(Rscratch, Rtemp, Rtemp); 6.65 - } 6.66 - __ add(O2_Klass, Rtemp, Rscratch); 6.67 - 6.68 - __ bind(search); 6.69 - 6.70 - __ ld_ptr(Rscratch, itableOffsetEntry::interface_offset_in_bytes(), Rtemp); 6.71 - { 6.72 - Label ok; 6.73 - 6.74 - // Check that entry is non-null. Null entries are probably a bytecode 6.75 - // problem. If the interface isn't implemented by the receiver class, 6.76 - // the VM should throw IncompatibleClassChangeError. linkResolver checks 6.77 - // this too but that's only if the entry isn't already resolved, so we 6.78 - // need to check again. 6.79 - __ br_notnull_short( Rtemp, Assembler::pt, ok); 6.80 - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); 6.81 - __ should_not_reach_here(); 6.82 - __ bind(ok); 6.83 - } 6.84 - 6.85 - __ cmp(Rinterface, Rtemp); 6.86 - __ brx(Assembler::notEqual, true, Assembler::pn, search); 6.87 - __ delayed()->add(Rscratch, itableOffsetEntry::size() * wordSize, Rscratch); 6.88 - 6.89 - // entry found and Rscratch points to it 6.90 - __ ld(Rscratch, itableOffsetEntry::offset_offset_in_bytes(), Rscratch); 6.91 - 6.92 - assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust instruction below"); 6.93 - __ sll(Rindex, exact_log2(itableMethodEntry::size() * wordSize), Rindex); // Rindex *= 8; 6.94 - __ add(Rscratch, Rindex, Rscratch); 6.95 - __ ld_ptr(O2_Klass, Rscratch, G5_method); 6.96 + // Get declaring interface class from method 6.97 + __ ld_ptr(Rmethod, Method::const_offset(), Rinterface); 6.98 + __ ld_ptr(Rinterface, ConstMethod::constants_offset(), Rinterface); 6.99 + __ ld_ptr(Rinterface, ConstantPool::pool_holder_offset_in_bytes(), Rinterface); 6.100 + 6.101 + // Get itable index from method 6.102 + const Register Rindex = G5_method; 6.103 + __ ld(Rmethod, Method::itable_index_offset(), Rindex); 6.104 + __ sub(Rindex, Method::itable_index_max, Rindex); 6.105 + __ neg(Rindex); 6.106 + 6.107 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 6.108 + O2_Klass, Rinterface, Rindex, 6.109 + // outputs: method, scan temp reg, temp reg 6.110 + G5_method, Rscratch, Rtemp, 6.111 + L_no_such_interface); 6.112 6.113 // Check for abstract method error. 6.114 { 6.115 @@ -3260,6 +3242,10 @@ 6.116 6.117 __ profile_arguments_type(G5_method, Rcall, Gargs, true); 6.118 __ call_from_interpreter(Rcall, Gargs, Rret); 6.119 + 6.120 + __ bind(L_no_such_interface); 6.121 + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); 6.122 + __ should_not_reach_here(); 6.123 } 6.124 6.125 void TemplateTable::invokehandle(int byte_no) {
7.1 --- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp Tue Aug 08 12:02:01 2017 +0100 7.2 +++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp Fri Sep 29 14:30:05 2017 -0400 7.3 @@ -1,5 +1,5 @@ 7.4 /* 7.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 7.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 7.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.8 * 7.9 * This code is free software; you can redistribute it and/or modify it 7.10 @@ -27,6 +27,7 @@ 7.11 #include "code/vtableStubs.hpp" 7.12 #include "interp_masm_sparc.hpp" 7.13 #include "memory/resourceArea.hpp" 7.14 +#include "oops/compiledICHolder.hpp" 7.15 #include "oops/instanceKlass.hpp" 7.16 #include "oops/klassVtable.hpp" 7.17 #include "runtime/sharedRuntime.hpp" 7.18 @@ -140,7 +141,8 @@ 7.19 MacroAssembler* masm = new MacroAssembler(&cb); 7.20 7.21 Register G3_Klass = G3_scratch; 7.22 - Register G5_interface = G5; // Passed in as an argument 7.23 + Register G5_icholder = G5; // Passed in as an argument 7.24 + Register G4_interface = G4_scratch; 7.25 Label search; 7.26 7.27 // Entry arguments: 7.28 @@ -164,14 +166,26 @@ 7.29 } 7.30 #endif /* PRODUCT */ 7.31 7.32 - Label throw_icce; 7.33 + Label L_no_such_interface; 7.34 7.35 Register L5_method = L5; 7.36 + 7.37 + // Receiver subtype check against REFC. 7.38 + __ ld_ptr(G5_icholder, CompiledICHolder::holder_klass_offset(), G4_interface); 7.39 __ lookup_interface_method(// inputs: rec. class, interface, itable index 7.40 - G3_Klass, G5_interface, itable_index, 7.41 + G3_Klass, G4_interface, itable_index, 7.42 + // outputs: scan temp. reg1, scan temp. reg2 7.43 + L5_method, L2, L3, 7.44 + L_no_such_interface, 7.45 + /*return_method=*/ false); 7.46 + 7.47 + // Get Method* and entrypoint for compiler 7.48 + __ ld_ptr(G5_icholder, CompiledICHolder::holder_metadata_offset(), G4_interface); 7.49 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 7.50 + G3_Klass, G4_interface, itable_index, 7.51 // outputs: method, scan temp. reg 7.52 L5_method, L2, L3, 7.53 - throw_icce); 7.54 + L_no_such_interface); 7.55 7.56 #ifndef PRODUCT 7.57 if (DebugVtables) { 7.58 @@ -197,7 +211,7 @@ 7.59 __ JMP(G3_scratch, 0); 7.60 __ delayed()->nop(); 7.61 7.62 - __ bind(throw_icce); 7.63 + __ bind(L_no_such_interface); 7.64 AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry()); 7.65 __ jump_to(icce, G3_scratch); 7.66 __ delayed()->restore(); 7.67 @@ -232,7 +246,7 @@ 7.68 MacroAssembler::instr_size_for_decode_klass_not_null() : 0); 7.69 return basic + slop; 7.70 } else { 7.71 - const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + 7.72 + const int basic = (48 LP64_ONLY(+ 6)) * BytesPerInstWord + 7.73 // shift;add for load_klass (only shift with zero heap based) 7.74 (UseCompressedClassPointers ? 7.75 MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
8.1 --- a/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Aug 08 12:02:01 2017 +0100 8.2 +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Sep 29 14:30:05 2017 -0400 8.3 @@ -1,5 +1,5 @@ 8.4 /* 8.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 8.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 8.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.8 * 8.9 * This code is free software; you can redistribute it and/or modify it 8.10 @@ -4853,8 +4853,13 @@ 8.11 RegisterOrConstant itable_index, 8.12 Register method_result, 8.13 Register scan_temp, 8.14 - Label& L_no_such_interface) { 8.15 - assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); 8.16 + Label& L_no_such_interface, 8.17 + bool return_method) { 8.18 + assert_different_registers(recv_klass, intf_klass, scan_temp); 8.19 + assert_different_registers(method_result, intf_klass, scan_temp); 8.20 + assert(recv_klass != method_result || !return_method, 8.21 + "recv_klass can be destroyed when method isn't needed"); 8.22 + 8.23 assert(itable_index.is_constant() || itable_index.as_register() == method_result, 8.24 "caller must use same register for non-constant itable index as for method"); 8.25 8.26 @@ -4876,9 +4881,11 @@ 8.27 round_to(scan_temp, BytesPerLong); 8.28 } 8.29 8.30 - // Adjust recv_klass by scaled itable_index, so we can free itable_index. 8.31 - assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); 8.32 - lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); 8.33 + if (return_method) { 8.34 + // Adjust recv_klass by scaled itable_index, so we can free itable_index. 8.35 + assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); 8.36 + lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); 8.37 + } 8.38 8.39 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { 8.40 // if (scan->interface() == intf) { 8.41 @@ -4912,9 +4919,11 @@ 8.42 8.43 bind(found_method); 8.44 8.45 - // Got a hit. 8.46 - movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); 8.47 - movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); 8.48 + if (return_method) { 8.49 + // Got a hit. 8.50 + movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); 8.51 + movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); 8.52 + } 8.53 } 8.54 8.55
9.1 --- a/src/cpu/x86/vm/macroAssembler_x86.hpp Tue Aug 08 12:02:01 2017 +0100 9.2 +++ b/src/cpu/x86/vm/macroAssembler_x86.hpp Fri Sep 29 14:30:05 2017 -0400 9.3 @@ -1,5 +1,5 @@ 9.4 /* 9.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 9.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 9.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.8 * 9.9 * This code is free software; you can redistribute it and/or modify it 9.10 @@ -525,7 +525,8 @@ 9.11 RegisterOrConstant itable_index, 9.12 Register method_result, 9.13 Register scan_temp, 9.14 - Label& no_such_interface); 9.15 + Label& no_such_interface, 9.16 + bool return_method = true); 9.17 9.18 // virtual method calling 9.19 void lookup_virtual_method(Register recv_klass,
10.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Aug 08 12:02:01 2017 +0100 10.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Sep 29 14:30:05 2017 -0400 10.3 @@ -1,5 +1,5 @@ 10.4 /* 10.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 10.6 + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 10.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.8 * 10.9 * This code is free software; you can redistribute it and/or modify it 10.10 @@ -955,7 +955,7 @@ 10.11 Label missed; 10.12 __ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); 10.13 __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset())); 10.14 - __ movptr(rbx, Address(holder, CompiledICHolder::holder_method_offset())); 10.15 + __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset())); 10.16 __ jcc(Assembler::notEqual, missed); 10.17 // Method might have been compiled since the call site was patched to 10.18 // interpreted if that is the case treat it as a miss so we can get
11.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Aug 08 12:02:01 2017 +0100 11.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Sep 29 14:30:05 2017 -0400 11.3 @@ -1,5 +1,5 @@ 11.4 /* 11.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 11.6 + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 11.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.8 * 11.9 * This code is free software; you can redistribute it and/or modify it 11.10 @@ -869,7 +869,7 @@ 11.11 { 11.12 __ load_klass(temp, receiver); 11.13 __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset())); 11.14 - __ movptr(rbx, Address(holder, CompiledICHolder::holder_method_offset())); 11.15 + __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset())); 11.16 __ jcc(Assembler::equal, ok); 11.17 __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); 11.18
12.1 --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Aug 08 12:02:01 2017 +0100 12.2 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Sep 29 14:30:05 2017 -0400 12.3 @@ -1,5 +1,5 @@ 12.4 /* 12.5 - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 12.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 12.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.8 * 12.9 * This code is free software; you can redistribute it and/or modify it 12.10 @@ -3099,11 +3099,11 @@ 12.11 void TemplateTable::invokeinterface(int byte_no) { 12.12 transition(vtos, vtos); 12.13 assert(byte_no == f1_byte, "use this argument"); 12.14 - prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 itable index 12.15 + prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 Method* 12.16 rcx, rdx); // recv, flags 12.17 12.18 - // rax: interface klass (from f1) 12.19 - // rbx: itable index (from f2) 12.20 + // rax: reference klass (from f1) 12.21 + // rbx: method (from f2) 12.22 // rcx: receiver 12.23 // rdx: flags 12.24 12.25 @@ -3124,10 +3124,29 @@ 12.26 __ null_check(rcx, oopDesc::klass_offset_in_bytes()); 12.27 __ load_klass(rdx, rcx); 12.28 12.29 + Label no_such_interface, no_such_method; 12.30 + 12.31 + // Receiver subtype check against REFC. 12.32 + // Superklass in rax. Subklass in rdx. Blows rcx, rdi. 12.33 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 12.34 + rdx, rax, noreg, 12.35 + // outputs: scan temp. reg, scan temp. reg 12.36 + rsi, rdi, 12.37 + no_such_interface, 12.38 + /*return_method=*/false); 12.39 + 12.40 + 12.41 // profile this call 12.42 + __ restore_bcp(); // rbcp was destroyed by receiver type check 12.43 __ profile_virtual_call(rdx, rsi, rdi); 12.44 12.45 - Label no_such_interface, no_such_method; 12.46 + // Get declaring interface class from method, and itable index 12.47 + __ movptr(rax, Address(rbx, Method::const_offset())); 12.48 + __ movptr(rax, Address(rax, ConstMethod::constants_offset())); 12.49 + __ movptr(rax, Address(rax, ConstantPool::pool_holder_offset_in_bytes())); 12.50 + __ movl(rbx, Address(rbx, Method::itable_index_offset())); 12.51 + __ subl(rbx, Method::itable_index_max); 12.52 + __ negl(rbx); 12.53 12.54 __ lookup_interface_method(// inputs: rec. class, interface, itable index 12.55 rdx, rax, rbx,
13.1 --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Tue Aug 08 12:02:01 2017 +0100 13.2 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Sep 29 14:30:05 2017 -0400 13.3 @@ -1,5 +1,5 @@ 13.4 /* 13.5 - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. 13.6 + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 13.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 13.8 * 13.9 * This code is free software; you can redistribute it and/or modify it 13.10 @@ -3150,11 +3150,11 @@ 13.11 void TemplateTable::invokeinterface(int byte_no) { 13.12 transition(vtos, vtos); 13.13 assert(byte_no == f1_byte, "use this argument"); 13.14 - prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 itable index 13.15 + prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 Method* 13.16 rcx, rdx); // recv, flags 13.17 13.18 - // rax: interface klass (from f1) 13.19 - // rbx: itable index (from f2) 13.20 + // rax: reference klass (from f1) 13.21 + // rbx: method (from f2) 13.22 // rcx: receiver 13.23 // rdx: flags 13.24 13.25 @@ -3175,10 +3175,28 @@ 13.26 __ null_check(rcx, oopDesc::klass_offset_in_bytes()); 13.27 __ load_klass(rdx, rcx); 13.28 13.29 + Label no_such_interface, no_such_method; 13.30 + 13.31 + // Receiver subtype check against REFC. 13.32 + // Superklass in rax. Subklass in rdx. Blows rcx, rdi. 13.33 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 13.34 + rdx, rax, noreg, 13.35 + // outputs: scan temp. reg, scan temp. reg 13.36 + r13, r14, 13.37 + no_such_interface, 13.38 + /*return_method=*/false); 13.39 + 13.40 // profile this call 13.41 + __ restore_bcp(); // rbcp was destroyed by receiver type check 13.42 __ profile_virtual_call(rdx, r13, r14); 13.43 13.44 - Label no_such_interface, no_such_method; 13.45 + // Get declaring interface class from method, and itable index 13.46 + __ movptr(rax, Address(rbx, Method::const_offset())); 13.47 + __ movptr(rax, Address(rax, ConstMethod::constants_offset())); 13.48 + __ movptr(rax, Address(rax, ConstantPool::pool_holder_offset_in_bytes())); 13.49 + __ movl(rbx, Address(rbx, Method::itable_index_offset())); 13.50 + __ subl(rbx, Method::itable_index_max); 13.51 + __ negl(rbx); 13.52 13.53 __ lookup_interface_method(// inputs: rec. class, interface, itable index 13.54 rdx, rax, rbx,
14.1 --- a/src/cpu/x86/vm/vtableStubs_x86_32.cpp Tue Aug 08 12:02:01 2017 +0100 14.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp Fri Sep 29 14:30:05 2017 -0400 14.3 @@ -1,5 +1,5 @@ 14.4 /* 14.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 14.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 14.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.8 * 14.9 * This code is free software; you can redistribute it and/or modify it 14.10 @@ -27,6 +27,7 @@ 14.11 #include "code/vtableStubs.hpp" 14.12 #include "interp_masm_x86.hpp" 14.13 #include "memory/resourceArea.hpp" 14.14 +#include "oops/compiledICHolder.hpp" 14.15 #include "oops/instanceKlass.hpp" 14.16 #include "oops/klassVtable.hpp" 14.17 #include "runtime/sharedRuntime.hpp" 14.18 @@ -147,7 +148,7 @@ 14.19 MacroAssembler* masm = new MacroAssembler(&cb); 14.20 14.21 // Entry arguments: 14.22 - // rax,: Interface 14.23 + // rax: CompiledICHolder 14.24 // rcx: Receiver 14.25 14.26 #ifndef PRODUCT 14.27 @@ -155,25 +156,42 @@ 14.28 __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); 14.29 } 14.30 #endif /* PRODUCT */ 14.31 - // get receiver (need to skip return address on top of stack) 14.32 14.33 - assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); 14.34 + // Most registers are in use; we'll use rax, rbx, rsi, rdi 14.35 + // (If we need to make rsi, rdi callee-save, do a push/pop here.) 14.36 + const Register recv_klass_reg = rsi; 14.37 + const Register holder_klass_reg = rax; // declaring interface klass (DECC) 14.38 + const Register resolved_klass_reg = rbx; // resolved interface klass (REFC) 14.39 + const Register temp_reg = rdi; 14.40 + 14.41 + const Register icholder_reg = rax; 14.42 + __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); 14.43 + __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); 14.44 + 14.45 + Label L_no_such_interface; 14.46 14.47 // get receiver klass (also an implicit null-check) 14.48 address npe_addr = __ pc(); 14.49 - __ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes())); 14.50 + assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); 14.51 + __ load_klass(recv_klass_reg, rcx); 14.52 14.53 - // Most registers are in use; we'll use rax, rbx, rsi, rdi 14.54 - // (If we need to make rsi, rdi callee-save, do a push/pop here.) 14.55 + // Receiver subtype check against REFC. 14.56 + // Destroys recv_klass_reg value. 14.57 + __ lookup_interface_method(// inputs: rec. class, interface 14.58 + recv_klass_reg, resolved_klass_reg, noreg, 14.59 + // outputs: scan temp. reg1, scan temp. reg2 14.60 + recv_klass_reg, temp_reg, 14.61 + L_no_such_interface, 14.62 + /*return_method=*/false); 14.63 + 14.64 + // Get selected method from declaring class and itable index 14.65 const Register method = rbx; 14.66 - Label throw_icce; 14.67 - 14.68 - // Get Method* and entrypoint for compiler 14.69 + __ load_klass(recv_klass_reg, rcx); // restore recv_klass_reg 14.70 __ lookup_interface_method(// inputs: rec. class, interface, itable index 14.71 - rsi, rax, itable_index, 14.72 + recv_klass_reg, holder_klass_reg, itable_index, 14.73 // outputs: method, scan temp. reg 14.74 - method, rdi, 14.75 - throw_icce); 14.76 + method, temp_reg, 14.77 + L_no_such_interface); 14.78 14.79 // method (rbx): Method* 14.80 // rcx: receiver 14.81 @@ -193,9 +211,10 @@ 14.82 address ame_addr = __ pc(); 14.83 __ jmp(Address(method, Method::from_compiled_offset())); 14.84 14.85 - __ bind(throw_icce); 14.86 + __ bind(L_no_such_interface); 14.87 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); 14.88 - masm->flush(); 14.89 + 14.90 + __ flush(); 14.91 14.92 if (PrintMiscellaneous && (WizardMode || Verbose)) { 14.93 tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", 14.94 @@ -220,7 +239,7 @@ 14.95 return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0); 14.96 } else { 14.97 // Itable stub size 14.98 - return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0); 14.99 + return (DebugVtables ? 256 : 116) + (CountCompiledCalls ? 6 : 0); 14.100 } 14.101 // In order to tune these parameters, run the JVM with VM options 14.102 // +PrintMiscellaneous and +WizardMode to see information about
15.1 --- a/src/cpu/x86/vm/vtableStubs_x86_64.cpp Tue Aug 08 12:02:01 2017 +0100 15.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_64.cpp Fri Sep 29 14:30:05 2017 -0400 15.3 @@ -1,5 +1,5 @@ 15.4 /* 15.5 - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. 15.6 + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 15.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.8 * 15.9 * This code is free software; you can redistribute it and/or modify it 15.10 @@ -27,6 +27,7 @@ 15.11 #include "code/vtableStubs.hpp" 15.12 #include "interp_masm_x86.hpp" 15.13 #include "memory/resourceArea.hpp" 15.14 +#include "oops/compiledICHolder.hpp" 15.15 #include "oops/instanceKlass.hpp" 15.16 #include "oops/klassVtable.hpp" 15.17 #include "runtime/sharedRuntime.hpp" 15.18 @@ -149,36 +150,50 @@ 15.19 #endif 15.20 15.21 // Entry arguments: 15.22 - // rax: Interface 15.23 + // rax: CompiledICHolder 15.24 // j_rarg0: Receiver 15.25 15.26 - // Free registers (non-args) are rax (interface), rbx 15.27 - 15.28 - // get receiver (need to skip return address on top of stack) 15.29 - 15.30 - assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); 15.31 - // get receiver klass (also an implicit null-check) 15.32 - address npe_addr = __ pc(); 15.33 - 15.34 // Most registers are in use; we'll use rax, rbx, r10, r11 15.35 // (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them) 15.36 - __ load_klass(r10, j_rarg0); 15.37 + const Register recv_klass_reg = r10; 15.38 + const Register holder_klass_reg = rax; // declaring interface klass (DECC) 15.39 + const Register resolved_klass_reg = rbx; // resolved interface klass (REFC) 15.40 + const Register temp_reg = r11; 15.41 + 15.42 + Label L_no_such_interface; 15.43 + 15.44 + const Register icholder_reg = rax; 15.45 + __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); 15.46 + __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); 15.47 + 15.48 + // get receiver klass (also an implicit null-check) 15.49 + assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); 15.50 + address npe_addr = __ pc(); 15.51 + __ load_klass(recv_klass_reg, j_rarg0); 15.52 + 15.53 + // Receiver subtype check against REFC. 15.54 + // Destroys recv_klass_reg value. 15.55 + __ lookup_interface_method(// inputs: rec. class, interface 15.56 + recv_klass_reg, resolved_klass_reg, noreg, 15.57 + // outputs: scan temp. reg1, scan temp. reg2 15.58 + recv_klass_reg, temp_reg, 15.59 + L_no_such_interface, 15.60 + /*return_method=*/false); 15.61 + 15.62 + // Get selected method from declaring class and itable index 15.63 + const Register method = rbx; 15.64 + __ load_klass(recv_klass_reg, j_rarg0); // restore recv_klass_reg 15.65 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 15.66 + recv_klass_reg, holder_klass_reg, itable_index, 15.67 + // outputs: method, scan temp. reg 15.68 + method, temp_reg, 15.69 + L_no_such_interface); 15.70 15.71 // If we take a trap while this arg is on the stack we will not 15.72 // be able to walk the stack properly. This is not an issue except 15.73 // when there are mistakes in this assembly code that could generate 15.74 // a spurious fault. Ask me how I know... 15.75 15.76 - const Register method = rbx; 15.77 - Label throw_icce; 15.78 - 15.79 - // Get Method* and entrypoint for compiler 15.80 - __ lookup_interface_method(// inputs: rec. class, interface, itable index 15.81 - r10, rax, itable_index, 15.82 - // outputs: method, scan temp. reg 15.83 - method, r11, 15.84 - throw_icce); 15.85 - 15.86 // method (rbx): Method* 15.87 // j_rarg0: receiver 15.88 15.89 @@ -199,7 +214,7 @@ 15.90 address ame_addr = __ pc(); 15.91 __ jmp(Address(method, Method::from_compiled_offset())); 15.92 15.93 - __ bind(throw_icce); 15.94 + __ bind(L_no_such_interface); 15.95 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); 15.96 15.97 __ flush(); 15.98 @@ -226,8 +241,8 @@ 15.99 (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); 15.100 } else { 15.101 // Itable stub size 15.102 - return (DebugVtables ? 512 : 74) + (CountCompiledCalls ? 13 : 0) + 15.103 - (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); 15.104 + return (DebugVtables ? 512 : 140) + (CountCompiledCalls ? 13 : 0) + 15.105 + (UseCompressedClassPointers ? 2 * MacroAssembler::instr_size_for_decode_klass_not_null() : 0); 15.106 } 15.107 // In order to tune these parameters, run the JVM with VM options 15.108 // +PrintMiscellaneous and +WizardMode to see information about
16.1 --- a/src/share/vm/code/compiledIC.cpp Tue Aug 08 12:02:01 2017 +0100 16.2 +++ b/src/share/vm/code/compiledIC.cpp Fri Sep 29 14:30:05 2017 -0400 16.3 @@ -1,5 +1,5 @@ 16.4 /* 16.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 16.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 16.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 16.8 * 16.9 * This code is free software; you can redistribute it and/or modify it 16.10 @@ -228,10 +228,13 @@ 16.11 #ifdef ASSERT 16.12 int index = call_info->resolved_method()->itable_index(); 16.13 assert(index == itable_index, "CallInfo pre-computes this"); 16.14 -#endif //ASSERT 16.15 InstanceKlass* k = call_info->resolved_method()->method_holder(); 16.16 assert(k->verify_itable_index(itable_index), "sanity check"); 16.17 - InlineCacheBuffer::create_transition_stub(this, k, entry); 16.18 +#endif //ASSERT 16.19 + CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(), 16.20 + call_info->resolved_klass()()); 16.21 + holder->claim(); 16.22 + InlineCacheBuffer::create_transition_stub(this, holder, entry); 16.23 } else { 16.24 assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable"); 16.25 // Can be different than selected_method->vtable_index(), due to package-private etc. 16.26 @@ -527,7 +530,14 @@ 16.27 16.28 bool CompiledIC::is_icholder_entry(address entry) { 16.29 CodeBlob* cb = CodeCache::find_blob_unsafe(entry); 16.30 - return (cb != NULL && cb->is_adapter_blob()); 16.31 + if (cb != NULL && cb->is_adapter_blob()) { 16.32 + return true; 16.33 + } 16.34 + // itable stubs also use CompiledICHolder 16.35 + if (VtableStubs::is_entry_point(entry) && VtableStubs::stub_containing(entry)->is_itable_stub()) { 16.36 + return true; 16.37 + } 16.38 + return false; 16.39 } 16.40 16.41 // ----------------------------------------------------------------------------
17.1 --- a/src/share/vm/code/compiledIC.hpp Tue Aug 08 12:02:01 2017 +0100 17.2 +++ b/src/share/vm/code/compiledIC.hpp Fri Sep 29 14:30:05 2017 -0400 17.3 @@ -1,5 +1,5 @@ 17.4 /* 17.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 17.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 17.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 17.8 * 17.9 * This code is free software; you can redistribute it and/or modify it 17.10 @@ -59,11 +59,11 @@ 17.11 // \ / \ / 17.12 // [4] \ / [4] \->-/ 17.13 // \->- Megamorphic -<-/ 17.14 -// (Method*) 17.15 +// (CompiledICHolder*) 17.16 // 17.17 -// The text in paranteses () refere to the value of the inline cache receiver (mov instruction) 17.18 +// The text in parentheses () refers to the value of the inline cache receiver (mov instruction) 17.19 // 17.20 -// The numbers in square brackets refere to the kind of transition: 17.21 +// The numbers in square brackets refer to the kind of transition: 17.22 // [1]: Initial fixup. Receiver it found from debug information 17.23 // [2]: Compilation of a method 17.24 // [3]: Recompilation of a method (note: only entry is changed. The Klass* must stay the same)
18.1 --- a/src/share/vm/code/nmethod.cpp Tue Aug 08 12:02:01 2017 +0100 18.2 +++ b/src/share/vm/code/nmethod.cpp Fri Sep 29 14:30:05 2017 -0400 18.3 @@ -1748,12 +1748,11 @@ 18.4 CompiledICHolder* cichk_oop = ic->cached_icholder(); 18.5 18.6 if (mark_on_stack) { 18.7 - Metadata::mark_on_stack(cichk_oop->holder_method()); 18.8 + Metadata::mark_on_stack(cichk_oop->holder_metadata()); 18.9 Metadata::mark_on_stack(cichk_oop->holder_klass()); 18.10 } 18.11 18.12 - if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) && 18.13 - cichk_oop->holder_klass()->is_loader_alive(is_alive)) { 18.14 + if (cichk_oop->is_loader_alive(is_alive)) { 18.15 return; 18.16 } 18.17 } else { 18.18 @@ -2180,7 +2179,7 @@ 18.19 CompiledIC *ic = CompiledIC_at(&iter); 18.20 if (ic->is_icholder_call()) { 18.21 CompiledICHolder* cichk = ic->cached_icholder(); 18.22 - f(cichk->holder_method()); 18.23 + f(cichk->holder_metadata()); 18.24 f(cichk->holder_klass()); 18.25 } else { 18.26 Metadata* ic_oop = ic->cached_metadata();
19.1 --- a/src/share/vm/interpreter/interpreterRuntime.cpp Tue Aug 08 12:02:01 2017 +0100 19.2 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Fri Sep 29 14:30:05 2017 -0400 19.3 @@ -786,6 +786,7 @@ 19.4 case CallInfo::itable_call: 19.5 cache_entry(thread)->set_itable_call( 19.6 bytecode, 19.7 + info.resolved_klass(), 19.8 info.resolved_method(), 19.9 info.itable_index()); 19.10 break;
20.1 --- a/src/share/vm/oops/compiledICHolder.cpp Tue Aug 08 12:02:01 2017 +0100 20.2 +++ b/src/share/vm/oops/compiledICHolder.cpp Fri Sep 29 14:30:05 2017 -0400 20.3 @@ -1,5 +1,5 @@ 20.4 /* 20.5 - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 20.6 + * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 20.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 20.8 * 20.9 * This code is free software; you can redistribute it and/or modify it 20.10 @@ -32,12 +32,28 @@ 20.11 volatile int CompiledICHolder::_live_not_claimed_count; 20.12 20.13 20.14 +bool CompiledICHolder::is_loader_alive(BoolObjectClosure* is_alive) { 20.15 + if (_holder_metadata->is_method()) { 20.16 + if (!((Method*)_holder_metadata)->method_holder()->is_loader_alive(is_alive)) { 20.17 + return false; 20.18 + } 20.19 + } else if (_holder_metadata->is_klass()) { 20.20 + if (!((Klass*)_holder_metadata)->is_loader_alive(is_alive)) { 20.21 + return false; 20.22 + } 20.23 + } 20.24 + if (!_holder_klass->is_loader_alive(is_alive)) { 20.25 + return false; 20.26 + } 20.27 + return true; 20.28 +} 20.29 + 20.30 // Printing 20.31 20.32 void CompiledICHolder::print_on(outputStream* st) const { 20.33 st->print("%s", internal_name()); 20.34 - st->print(" - method: "); holder_method()->print_value_on(st); st->cr(); 20.35 - st->print(" - klass: "); holder_klass()->print_value_on(st); st->cr(); 20.36 + st->print(" - metadata: "); holder_metadata()->print_value_on(st); st->cr(); 20.37 + st->print(" - klass: "); holder_klass()->print_value_on(st); st->cr(); 20.38 } 20.39 20.40 void CompiledICHolder::print_value_on(outputStream* st) const { 20.41 @@ -48,6 +64,6 @@ 20.42 // Verification 20.43 20.44 void CompiledICHolder::verify_on(outputStream* st) { 20.45 - guarantee(holder_method()->is_method(), "should be method"); 20.46 + guarantee(holder_metadata()->is_method() || holder_metadata()->is_klass(), "should be method or klass"); 20.47 guarantee(holder_klass()->is_klass(), "should be klass"); 20.48 }
21.1 --- a/src/share/vm/oops/compiledICHolder.hpp Tue Aug 08 12:02:01 2017 +0100 21.2 +++ b/src/share/vm/oops/compiledICHolder.hpp Fri Sep 29 14:30:05 2017 -0400 21.3 @@ -1,5 +1,5 @@ 21.4 /* 21.5 - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. 21.6 + * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 21.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 21.8 * 21.9 * This code is free software; you can redistribute it and/or modify it 21.10 @@ -28,8 +28,9 @@ 21.11 #include "oops/oop.hpp" 21.12 21.13 // A CompiledICHolder* is a helper object for the inline cache implementation. 21.14 -// It holds an intermediate value (method+klass pair) used when converting from 21.15 -// compiled to an interpreted call. 21.16 +// It holds: 21.17 +// (1) (method+klass pair) when converting from compiled to an interpreted call 21.18 +// (2) (klass+klass pair) when calling itable stub from megamorphic compiled call 21.19 // 21.20 // These are always allocated in the C heap and are freed during a 21.21 // safepoint by the ICBuffer logic. It's unsafe to free them earlier 21.22 @@ -44,14 +45,14 @@ 21.23 static volatile int _live_not_claimed_count; // allocated but not yet in use so not 21.24 // reachable by iterating over nmethods 21.25 21.26 - Method* _holder_method; 21.27 + Metadata* _holder_metadata; 21.28 Klass* _holder_klass; // to avoid name conflict with oopDesc::_klass 21.29 CompiledICHolder* _next; 21.30 21.31 public: 21.32 // Constructor 21.33 - CompiledICHolder(Method* method, Klass* klass) 21.34 - : _holder_method(method), _holder_klass(klass) { 21.35 + CompiledICHolder(Metadata* metadata, Klass* klass) 21.36 + : _holder_metadata(metadata), _holder_klass(klass) { 21.37 #ifdef ASSERT 21.38 Atomic::inc(&_live_count); 21.39 Atomic::inc(&_live_not_claimed_count); 21.40 @@ -69,19 +70,20 @@ 21.41 static int live_not_claimed_count() { return _live_not_claimed_count; } 21.42 21.43 // accessors 21.44 - Method* holder_method() const { return _holder_method; } 21.45 Klass* holder_klass() const { return _holder_klass; } 21.46 + Metadata* holder_metadata() const { return _holder_metadata; } 21.47 21.48 - void set_holder_method(Method* m) { _holder_method = m; } 21.49 - void set_holder_klass(Klass* k) { _holder_klass = k; } 21.50 + void set_holder_metadata(Metadata* m) { _holder_metadata = m; } 21.51 + void set_holder_klass(Klass* k) { _holder_klass = k; } 21.52 21.53 - // interpreter support (offsets in bytes) 21.54 - static int holder_method_offset() { return offset_of(CompiledICHolder, _holder_method); } 21.55 + static int holder_metadata_offset() { return offset_of(CompiledICHolder, _holder_metadata); } 21.56 static int holder_klass_offset() { return offset_of(CompiledICHolder, _holder_klass); } 21.57 21.58 CompiledICHolder* next() { return _next; } 21.59 void set_next(CompiledICHolder* n) { _next = n; } 21.60 21.61 + bool is_loader_alive(BoolObjectClosure* is_alive); 21.62 + 21.63 // Verify 21.64 void verify_on(outputStream* st); 21.65
22.1 --- a/src/share/vm/oops/cpCache.cpp Tue Aug 08 12:02:01 2017 +0100 22.2 +++ b/src/share/vm/oops/cpCache.cpp Fri Sep 29 14:30:05 2017 -0400 22.3 @@ -1,5 +1,5 @@ 22.4 /* 22.5 - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. 22.6 + * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 22.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 22.8 * 22.9 * This code is free software; you can redistribute it and/or modify it 22.10 @@ -259,14 +259,16 @@ 22.11 set_direct_or_vtable_call(invoke_code, method, index, false); 22.12 } 22.13 22.14 -void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { 22.15 +void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, 22.16 + KlassHandle referenced_klass, 22.17 + methodHandle method, int index) { 22.18 assert(method->method_holder()->verify_itable_index(index), ""); 22.19 assert(invoke_code == Bytecodes::_invokeinterface, ""); 22.20 InstanceKlass* interf = method->method_holder(); 22.21 assert(interf->is_interface(), "must be an interface"); 22.22 assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); 22.23 - set_f1(interf); 22.24 - set_f2(index); 22.25 + set_f1(referenced_klass()); 22.26 + set_f2((intx)method()); 22.27 set_method_flags(as_TosState(method->result_type()), 22.28 0, // no option bits 22.29 method()->size_of_parameters()); 22.30 @@ -433,10 +435,27 @@ 22.31 22.32 22.33 #if INCLUDE_JVMTI 22.34 + 22.35 +void log_adjust(const char* entry_type, Method* old_method, Method* new_method, bool* trace_name_printed) { 22.36 + if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { 22.37 + if (!(*trace_name_printed)) { 22.38 + // RC_TRACE_MESG macro has an embedded ResourceMark 22.39 + RC_TRACE_MESG(("adjust: name=%s", 22.40 + old_method->method_holder()->external_name())); 22.41 + *trace_name_printed = true; 22.42 + } 22.43 + // RC_TRACE macro has an embedded ResourceMark 22.44 + RC_TRACE(0x00400000, ("cpc %s entry update: %s(%s)", 22.45 + entry_type, 22.46 + new_method->name()->as_C_string(), 22.47 + new_method->signature()->as_C_string())); 22.48 + } 22.49 +} 22.50 + 22.51 // RedefineClasses() API support: 22.52 // If this ConstantPoolCacheEntry refers to old_method then update it 22.53 // to refer to new_method. 22.54 -bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, 22.55 +void ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, 22.56 Method* new_method, bool * trace_name_printed) { 22.57 22.58 if (is_vfinal()) { 22.59 @@ -445,69 +464,34 @@ 22.60 // match old_method so need an update 22.61 // NOTE: can't use set_f2_as_vfinal_method as it asserts on different values 22.62 _f2 = (intptr_t)new_method; 22.63 - if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { 22.64 - if (!(*trace_name_printed)) { 22.65 - // RC_TRACE_MESG macro has an embedded ResourceMark 22.66 - RC_TRACE_MESG(("adjust: name=%s", 22.67 - old_method->method_holder()->external_name())); 22.68 - *trace_name_printed = true; 22.69 - } 22.70 - // RC_TRACE macro has an embedded ResourceMark 22.71 - RC_TRACE(0x00400000, ("cpc vf-entry update: %s(%s)", 22.72 - new_method->name()->as_C_string(), 22.73 - new_method->signature()->as_C_string())); 22.74 - } 22.75 - return true; 22.76 } 22.77 - 22.78 - // f1() is not used with virtual entries so bail out 22.79 - return false; 22.80 + return; 22.81 } 22.82 22.83 - if (_f1 == NULL) { 22.84 - // NULL f1() means this is a virtual entry so bail out 22.85 - // We are assuming that the vtable index does not need change. 22.86 - return false; 22.87 + assert (_f1 != NULL, "should not call with uninteresting entry"); 22.88 + 22.89 + if (!(_f1->is_method())) { 22.90 + // _f1 is a Klass* for an interface, _f2 is the method 22.91 + if (f2_as_interface_method() == old_method) { 22.92 + _f2 = (intptr_t)new_method; 22.93 + log_adjust("interface", old_method, new_method, trace_name_printed); 22.94 + } 22.95 + } else if (_f1 == old_method) { 22.96 + _f1 = new_method; 22.97 + log_adjust("special, static or dynamic", old_method, new_method, trace_name_printed); 22.98 } 22.99 - 22.100 - if (_f1 == old_method) { 22.101 - _f1 = new_method; 22.102 - if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { 22.103 - if (!(*trace_name_printed)) { 22.104 - // RC_TRACE_MESG macro has an embedded ResourceMark 22.105 - RC_TRACE_MESG(("adjust: name=%s", 22.106 - old_method->method_holder()->external_name())); 22.107 - *trace_name_printed = true; 22.108 - } 22.109 - // RC_TRACE macro has an embedded ResourceMark 22.110 - RC_TRACE(0x00400000, ("cpc entry update: %s(%s)", 22.111 - new_method->name()->as_C_string(), 22.112 - new_method->signature()->as_C_string())); 22.113 - } 22.114 - return true; 22.115 - } 22.116 - 22.117 - return false; 22.118 } 22.119 22.120 // a constant pool cache entry should never contain old or obsolete methods 22.121 bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() { 22.122 - if (is_vfinal()) { 22.123 - // virtual and final so _f2 contains method ptr instead of vtable index 22.124 - Metadata* f2 = (Metadata*)_f2; 22.125 - // Return false if _f2 refers to an old or an obsolete method. 22.126 - // _f2 == NULL || !_f2->is_method() are just as unexpected here. 22.127 - return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() && 22.128 - !((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete()); 22.129 - } else if (_f1 == NULL || 22.130 - (NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) { 22.131 - // _f1 == NULL || !_f1->is_method() are OK here 22.132 + Method* m = get_interesting_method_entry(NULL); 22.133 + // return false if m refers to a non-deleted old or obsolete method 22.134 + if (m != NULL) { 22.135 + assert(m->is_valid() && m->is_method(), "m is a valid method"); 22.136 + return !m->is_old() && !m->is_obsolete(); // old is always set for old and obsolete 22.137 + } else { 22.138 return true; 22.139 } 22.140 - // return false if _f1 refers to a non-deleted old or obsolete method 22.141 - return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() && 22.142 - (f1_as_method()->is_deleted() || 22.143 - (!f1_as_method()->is_old() && !f1_as_method()->is_obsolete()))); 22.144 } 22.145 22.146 Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) { 22.147 @@ -524,10 +508,11 @@ 22.148 return NULL; 22.149 } else { 22.150 if (!(_f1->is_method())) { 22.151 - // _f1 can also contain a Klass* for an interface 22.152 - return NULL; 22.153 + // _f1 is a Klass* for an interface 22.154 + m = f2_as_interface_method(); 22.155 + } else { 22.156 + m = f1_as_method(); 22.157 } 22.158 - m = f1_as_method(); 22.159 } 22.160 assert(m != NULL && m->is_method(), "sanity check"); 22.161 if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) {
23.1 --- a/src/share/vm/oops/cpCache.hpp Tue Aug 08 12:02:01 2017 +0100 23.2 +++ b/src/share/vm/oops/cpCache.hpp Fri Sep 29 14:30:05 2017 -0400 23.3 @@ -1,5 +1,5 @@ 23.4 /* 23.5 - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. 23.6 + * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 23.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 23.8 * 23.9 * This code is free software; you can redistribute it and/or modify it 23.10 @@ -248,6 +248,7 @@ 23.11 23.12 void set_itable_call( 23.13 Bytecodes::Code invoke_code, // the bytecode used; must be invokeinterface 23.14 + KlassHandle referenced_klass, // the referenced klass in the InterfaceMethodref 23.15 methodHandle method, // the resolved interface method 23.16 int itable_index // index into itable for the method 23.17 ); 23.18 @@ -344,6 +345,7 @@ 23.19 bool is_f1_null() const { Metadata* f1 = f1_ord(); return f1 == NULL; } // classifies a CPC entry as unbound 23.20 int f2_as_index() const { assert(!is_vfinal(), ""); return (int) _f2; } 23.21 Method* f2_as_vfinal_method() const { assert(is_vfinal(), ""); return (Method*)_f2; } 23.22 + Method* f2_as_interface_method() const { assert(bytecode_1() == Bytecodes::_invokeinterface, ""); return (Method*)_f2; } 23.23 int field_index() const { assert(is_field_entry(), ""); return (_flags & field_index_mask); } 23.24 int parameter_size() const { assert(is_method_entry(), ""); return (_flags & parameter_size_mask); } 23.25 bool is_volatile() const { return (_flags & (1 << is_volatile_shift)) != 0; } 23.26 @@ -374,7 +376,7 @@ 23.27 // trace_name_printed is set to true if the current call has 23.28 // printed the klass name so that other routines in the adjust_* 23.29 // group don't print the klass name. 23.30 - bool adjust_method_entry(Method* old_method, Method* new_method, 23.31 + void adjust_method_entry(Method* old_method, Method* new_method, 23.32 bool* trace_name_printed); 23.33 bool check_no_old_or_obsolete_entries(); 23.34 Method* get_interesting_method_entry(Klass* k);
24.1 --- a/src/share/vm/oops/klassVtable.cpp Tue Aug 08 12:02:01 2017 +0100 24.2 +++ b/src/share/vm/oops/klassVtable.cpp Fri Sep 29 14:30:05 2017 -0400 24.3 @@ -1204,7 +1204,6 @@ 24.4 Array<Method*>* methods = InstanceKlass::cast(interf_h())->methods(); 24.5 int nof_methods = methods->length(); 24.6 HandleMark hm; 24.7 - assert(nof_methods > 0, "at least one method must exist for interface to be in vtable"); 24.8 Handle interface_loader (THREAD, InstanceKlass::cast(interf_h())->class_loader()); 24.9 24.10 int ime_count = method_count_for_interface(interf_h()); 24.11 @@ -1386,8 +1385,10 @@ 24.12 } 24.13 } 24.14 24.15 - // Only count interfaces with at least one method 24.16 - if (method_count > 0) { 24.17 + // Visit all interfaces which either have any methods or can participate in receiver type check. 24.18 + // We do not bother to count methods in transitive interfaces, although that would allow us to skip 24.19 + // this step in the rare case of a zero-method interface extending another zero-method interface. 24.20 + if (method_count > 0 || InstanceKlass::cast(intf)->transitive_interfaces()->length() > 0) { 24.21 blk->doit(intf, method_count); 24.22 } 24.23 }
25.1 --- a/src/share/vm/oops/method.hpp Tue Aug 08 12:02:01 2017 +0100 25.2 +++ b/src/share/vm/oops/method.hpp Fri Sep 29 14:30:05 2017 -0400 25.3 @@ -1,5 +1,5 @@ 25.4 /* 25.5 - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 25.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 25.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 25.8 * 25.9 * This code is free software; you can redistribute it and/or modify it 25.10 @@ -661,6 +661,7 @@ 25.11 static ByteSize from_interpreted_offset() { return byte_offset_of(Method, _from_interpreted_entry ); } 25.12 static ByteSize interpreter_entry_offset() { return byte_offset_of(Method, _i2i_entry ); } 25.13 static ByteSize signature_handler_offset() { return in_ByteSize(sizeof(Method) + wordSize); } 25.14 + static ByteSize itable_index_offset() { return byte_offset_of(Method, _vtable_index ); } 25.15 25.16 // for code generation 25.17 static int method_data_offset_in_bytes() { return offset_of(Method, _method_data); }
26.1 --- a/src/share/vm/runtime/vmStructs.cpp Tue Aug 08 12:02:01 2017 +0100 26.2 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Sep 29 14:30:05 2017 -0400 26.3 @@ -278,7 +278,7 @@ 26.4 volatile_nonstatic_field(ArrayKlass, _lower_dimension, Klass*) \ 26.5 nonstatic_field(ArrayKlass, _vtable_len, int) \ 26.6 nonstatic_field(ArrayKlass, _component_mirror, oop) \ 26.7 - nonstatic_field(CompiledICHolder, _holder_method, Method*) \ 26.8 + nonstatic_field(CompiledICHolder, _holder_metadata, Metadata*) \ 26.9 nonstatic_field(CompiledICHolder, _holder_klass, Klass*) \ 26.10 nonstatic_field(ConstantPool, _tags, Array<u1>*) \ 26.11 nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/test/runtime/RedefineTests/RedefineInterfaceCall.java Fri Sep 29 14:30:05 2017 -0400 27.3 @@ -0,0 +1,83 @@ 27.4 +/* 27.5 + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 27.7 + * 27.8 + * This code is free software; you can redistribute it and/or modify it 27.9 + * under the terms of the GNU General Public License version 2 only, as 27.10 + * published by the Free Software Foundation. 27.11 + * 27.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 27.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 27.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 27.15 + * version 2 for more details (a copy is included in the LICENSE file that 27.16 + * accompanied this code). 27.17 + * 27.18 + * You should have received a copy of the GNU General Public License version 27.19 + * 2 along with this work; if not, write to the Free Software Foundation, 27.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 27.21 + * 27.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 27.23 + * or visit www.oracle.com if you need additional information or have any 27.24 + * questions. 27.25 + */ 27.26 + 27.27 +/* 27.28 + * @test 27.29 + * @bug 8174962 27.30 + * @summary Redefine class with interface method call 27.31 + * @library /testlibrary /test/lib 27.32 + * @modules java.base/jdk.internal.misc 27.33 + * @modules java.compiler 27.34 + * java.instrument 27.35 + * jdk.jartool/sun.tools.jar 27.36 + * @run main RedefineClassHelper 27.37 + * @run main/othervm -javaagent:redefineagent.jar RedefineInterfaceCall 27.38 + */ 27.39 + 27.40 +import static jdk.testlibrary.Asserts.assertEquals; 27.41 + 27.42 +interface I1 { default int m() { return 0; } } 27.43 +interface I2 extends I1 {} 27.44 + 27.45 +public class RedefineInterfaceCall { 27.46 + 27.47 + public static class C implements I2 { 27.48 + public int test(I2 i) { 27.49 + return i.m(); // invokeinterface cpCacheEntry 27.50 + } 27.51 + } 27.52 + 27.53 + static String newI1 = 27.54 + "interface I1 { default int m() { return 1; } }"; 27.55 + 27.56 + static String newC = 27.57 + "public class RedefineInterfaceCall$C implements I2 { " + 27.58 + " public int test(I2 i) { " + 27.59 + " return i.m(); " + 27.60 + " } " + 27.61 + "} "; 27.62 + 27.63 + static int test(I2 i) { 27.64 + return i.m(); // invokeinterface cpCacheEntry 27.65 + } 27.66 + 27.67 + public static void main(String[] args) throws Exception { 27.68 + C c = new C(); 27.69 + 27.70 + assertEquals(test(c), 0); 27.71 + assertEquals(c.test(c), 0); 27.72 + 27.73 + RedefineClassHelper.redefineClass(C.class, newC); 27.74 + 27.75 + assertEquals(c.test(c), 0); 27.76 + 27.77 + RedefineClassHelper.redefineClass(I1.class, newI1); 27.78 + 27.79 + assertEquals(test(c), 1); 27.80 + assertEquals(c.test(c), 1); 27.81 + 27.82 + RedefineClassHelper.redefineClass(C.class, newC); 27.83 + 27.84 + assertEquals(c.test(c), 1); 27.85 + } 27.86 +}