Fri, 06 Mar 2009 21:36:50 -0800
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
Summary: Code in vtableStubs and templateTable moved into MacroAssembler.
Reviewed-by: kvn
1.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Wed Mar 04 09:58:39 2009 -0800 1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Fri Mar 06 21:36:50 2009 -0800 1.3 @@ -2638,6 +2638,135 @@ 1.4 } 1.5 1.6 1.7 +void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { 1.8 + assert(dest.register_or_noreg() != G0, "lost side effect"); 1.9 + if ((src.is_constant() && src.as_constant() == 0) || 1.10 + (src.is_register() && src.as_register() == G0)) { 1.11 + // do nothing 1.12 + } else if (dest.is_register()) { 1.13 + add(dest.as_register(), ensure_rs2(src, temp), dest.as_register()); 1.14 + } else if (src.is_constant()) { 1.15 + intptr_t res = dest.as_constant() + src.as_constant(); 1.16 + dest = RegisterConstant(res); // side effect seen by caller 1.17 + } else { 1.18 + assert(temp != noreg, "cannot handle constant += register"); 1.19 + add(src.as_register(), ensure_rs2(dest, temp), temp); 1.20 + dest = RegisterConstant(temp); // side effect seen by caller 1.21 + } 1.22 +} 1.23 + 1.24 +void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { 1.25 + assert(dest.register_or_noreg() != G0, "lost side effect"); 1.26 + if (!is_simm13(src.constant_or_zero())) 1.27 + src = (src.as_constant() & 0xFF); 1.28 + if ((src.is_constant() && src.as_constant() == 0) || 1.29 + (src.is_register() && src.as_register() == G0)) { 1.30 + // do nothing 1.31 + } else if (dest.is_register()) { 1.32 + sll_ptr(dest.as_register(), src, dest.as_register()); 1.33 + } else if (src.is_constant()) { 1.34 + intptr_t res = dest.as_constant() << src.as_constant(); 1.35 + dest = RegisterConstant(res); // side effect seen by caller 1.36 + } else { 1.37 + assert(temp != noreg, "cannot handle constant <<= register"); 1.38 + set(dest.as_constant(), temp); 1.39 + sll_ptr(temp, src, temp); 1.40 + dest = RegisterConstant(temp); // side effect seen by caller 1.41 + } 1.42 +} 1.43 + 1.44 + 1.45 +// Look up the method for a megamorphic invokeinterface call. 1.46 +// The target method is determined by <intf_klass, itable_index>. 1.47 +// The receiver klass is in recv_klass. 1.48 +// On success, the result will be in method_result, and execution falls through. 1.49 +// On failure, execution transfers to the given label. 1.50 +void MacroAssembler::lookup_interface_method(Register recv_klass, 1.51 + Register intf_klass, 1.52 + RegisterConstant itable_index, 1.53 + Register method_result, 1.54 + Register scan_temp, 1.55 + Register sethi_temp, 1.56 + Label& L_no_such_interface) { 1.57 + assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); 1.58 + assert(itable_index.is_constant() || itable_index.as_register() == method_result, 1.59 + "caller must use same register for non-constant itable index as for method"); 1.60 + 1.61 + // Compute start of first itableOffsetEntry (which is at the end of the vtable) 1.62 + int vtable_base = instanceKlass::vtable_start_offset() * wordSize; 1.63 + int scan_step = itableOffsetEntry::size() * wordSize; 1.64 + int vte_size = vtableEntry::size() * wordSize; 1.65 + 1.66 + lduw(recv_klass, instanceKlass::vtable_length_offset() * wordSize, scan_temp); 1.67 + // %%% We should store the aligned, prescaled offset in the klassoop. 1.68 + // Then the next several instructions would fold away. 1.69 + 1.70 + int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0); 1.71 + int itb_offset = vtable_base; 1.72 + if (round_to_unit != 0) { 1.73 + // hoist first instruction of round_to(scan_temp, BytesPerLong): 1.74 + itb_offset += round_to_unit - wordSize; 1.75 + } 1.76 + int itb_scale = exact_log2(vtableEntry::size() * wordSize); 1.77 + sll(scan_temp, itb_scale, scan_temp); 1.78 + add(scan_temp, itb_offset, scan_temp); 1.79 + if (round_to_unit != 0) { 1.80 + // Round up to align_object_offset boundary 1.81 + // see code for instanceKlass::start_of_itable! 1.82 + // Was: round_to(scan_temp, BytesPerLong); 1.83 + // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp); 1.84 + and3(scan_temp, -round_to_unit, scan_temp); 1.85 + } 1.86 + add(recv_klass, scan_temp, scan_temp); 1.87 + 1.88 + // Adjust recv_klass by scaled itable_index, so we can free itable_index. 1.89 + RegisterConstant itable_offset = itable_index; 1.90 + regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); 1.91 + regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); 1.92 + add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass); 1.93 + 1.94 + // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { 1.95 + // if (scan->interface() == intf) { 1.96 + // result = (klass + scan->offset() + itable_index); 1.97 + // } 1.98 + // } 1.99 + Label search, found_method; 1.100 + 1.101 + for (int peel = 1; peel >= 0; peel--) { 1.102 + // %%%% Could load both offset and interface in one ldx, if they were 1.103 + // in the opposite order. This would save a load. 1.104 + ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result); 1.105 + 1.106 + // Check that this entry is non-null. A null entry means that 1.107 + // the receiver class doesn't implement the interface, and wasn't the 1.108 + // same as when the caller was compiled. 1.109 + bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface); 1.110 + delayed()->cmp(method_result, intf_klass); 1.111 + 1.112 + if (peel) { 1.113 + brx(Assembler::equal, false, Assembler::pt, found_method); 1.114 + } else { 1.115 + brx(Assembler::notEqual, false, Assembler::pn, search); 1.116 + // (invert the test to fall through to found_method...) 1.117 + } 1.118 + delayed()->add(scan_temp, scan_step, scan_temp); 1.119 + 1.120 + if (!peel) break; 1.121 + 1.122 + bind(search); 1.123 + } 1.124 + 1.125 + bind(found_method); 1.126 + 1.127 + // Got a hit. 1.128 + int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); 1.129 + // scan_temp[-scan_step] points to the vtable offset we need 1.130 + ito_offset -= scan_step; 1.131 + lduw(scan_temp, ito_offset, scan_temp); 1.132 + ld_ptr(recv_klass, scan_temp, method_result); 1.133 +} 1.134 + 1.135 + 1.136 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, 1.137 Register temp_reg, 1.138 Label& done, Label* slow_case,
2.1 --- a/src/cpu/sparc/vm/assembler_sparc.hpp Wed Mar 04 09:58:39 2009 -0800 2.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Fri Mar 06 21:36:50 2009 -0800 2.3 @@ -1859,6 +1859,7 @@ 2.4 // Functions for isolating 64 bit shifts for LP64 2.5 inline void sll_ptr( Register s1, Register s2, Register d ); 2.6 inline void sll_ptr( Register s1, int imm6a, Register d ); 2.7 + inline void sll_ptr( Register s1, RegisterConstant s2, Register d ); 2.8 inline void srl_ptr( Register s1, Register s2, Register d ); 2.9 inline void srl_ptr( Register s1, int imm6a, Register d ); 2.10 2.11 @@ -1986,6 +1987,25 @@ 2.12 void load_sized_value(Register s1, RegisterConstant s2, Register d, 2.13 int size_in_bytes, bool is_signed); 2.14 2.15 + // Helpers for address formation. 2.16 + // They update the dest in place, whether it is a register or constant. 2.17 + // They emit no code at all if src is a constant zero. 2.18 + // If dest is a constant and src is a register, the temp argument 2.19 + // is required, and becomes the result. 2.20 + // If dest is a register and src is a non-simm13 constant, 2.21 + // the temp argument is required, and is used to materialize the constant. 2.22 + void regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, 2.23 + Register temp = noreg ); 2.24 + void regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, 2.25 + Register temp = noreg ); 2.26 + RegisterConstant ensure_rs2(RegisterConstant rs2, Register sethi_temp) { 2.27 + guarantee(sethi_temp != noreg, "constant offset overflow"); 2.28 + if (is_simm13(rs2.constant_or_zero())) 2.29 + return rs2; // register or short constant 2.30 + set(rs2.as_constant(), sethi_temp); 2.31 + return sethi_temp; 2.32 + } 2.33 + 2.34 // -------------------------------------------------- 2.35 2.36 public: 2.37 @@ -2299,6 +2319,14 @@ 2.38 ); 2.39 void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); 2.40 2.41 + // interface method calling 2.42 + void lookup_interface_method(Register recv_klass, 2.43 + Register intf_klass, 2.44 + RegisterConstant itable_index, 2.45 + Register method_result, 2.46 + Register temp_reg, Register temp2_reg, 2.47 + Label& no_such_interface); 2.48 + 2.49 // Stack overflow checking 2.50 2.51 // Note: this clobbers G3_scratch
3.1 --- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Mar 04 09:58:39 2009 -0800 3.2 +++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp Fri Mar 06 21:36:50 2009 -0800 3.3 @@ -455,6 +455,11 @@ 3.4 #endif 3.5 } 3.6 3.7 +inline void MacroAssembler::sll_ptr( Register s1, RegisterConstant s2, Register d ) { 3.8 + if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); 3.9 + else sll_ptr(s1, s2.as_constant(), d); 3.10 +} 3.11 + 3.12 // Use the right branch for the platform 3.13 3.14 inline void MacroAssembler::br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) {
4.1 --- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp Wed Mar 04 09:58:39 2009 -0800 4.2 +++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp Fri Mar 06 21:36:50 2009 -0800 4.3 @@ -106,6 +106,15 @@ 4.4 __ delayed()->nop(); 4.5 4.6 masm->flush(); 4.7 + 4.8 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 4.9 + tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", 4.10 + vtable_index, s->entry_point(), 4.11 + (int)(s->code_end() - s->entry_point()), 4.12 + (int)(s->code_end() - __ pc())); 4.13 + } 4.14 + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 4.15 + 4.16 s->set_exception_points(npe_addr, ame_addr); 4.17 return s; 4.18 } 4.19 @@ -113,9 +122,9 @@ 4.20 4.21 // NOTE: %%%% if any change is made to this stub make sure that the function 4.22 // pd_code_size_limit is changed to ensure the correct size for VtableStub 4.23 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) { 4.24 +VtableStub* VtableStubs::create_itable_stub(int itable_index) { 4.25 const int sparc_code_length = VtableStub::pd_code_size_limit(false); 4.26 - VtableStub* s = new(sparc_code_length) VtableStub(false, vtable_index); 4.27 + VtableStub* s = new(sparc_code_length) VtableStub(false, itable_index); 4.28 ResourceMark rm; 4.29 CodeBuffer cb(s->entry_point(), sparc_code_length); 4.30 MacroAssembler* masm = new MacroAssembler(&cb); 4.31 @@ -139,7 +148,6 @@ 4.32 // are passed in the %o registers. Instead, longs are passed in G1 and G4 4.33 // and so those registers are not available here. 4.34 __ save(SP,-frame::register_save_words*wordSize,SP); 4.35 - Register I0_receiver = I0; // Location of receiver after save 4.36 4.37 #ifndef PRODUCT 4.38 if (CountCompiledCalls) { 4.39 @@ -151,63 +159,31 @@ 4.40 } 4.41 #endif /* PRODUCT */ 4.42 4.43 - // load start of itable entries into L0 register 4.44 - const int base = instanceKlass::vtable_start_offset() * wordSize; 4.45 - __ ld(Address(G3_klassOop, 0, instanceKlass::vtable_length_offset() * wordSize), L0); 4.46 + Label throw_icce; 4.47 4.48 - // %%% Could store the aligned, prescaled offset in the klassoop. 4.49 - __ sll(L0, exact_log2(vtableEntry::size() * wordSize), L0); 4.50 - // see code for instanceKlass::start_of_itable! 4.51 - const int vtable_alignment = align_object_offset(1); 4.52 - assert(vtable_alignment == 1 || vtable_alignment == 2, ""); 4.53 - const int odd_bit = vtableEntry::size() * wordSize; 4.54 - if (vtable_alignment == 2) { 4.55 - __ and3(L0, odd_bit, L1); // isolate the odd bit 4.56 - } 4.57 - __ add(G3_klassOop, L0, L0); 4.58 - if (vtable_alignment == 2) { 4.59 - __ add(L0, L1, L0); // double the odd bit, to align up 4.60 - } 4.61 - 4.62 - // Loop over all itable entries until desired interfaceOop (G5_interface) found 4.63 - __ bind(search); 4.64 - 4.65 - // %%%% Could load both offset and interface in one ldx, if they were 4.66 - // in the opposite order. This would save a load. 4.67 - __ ld_ptr(L0, base + itableOffsetEntry::interface_offset_in_bytes(), L1); 4.68 - 4.69 - // If the entry is NULL then we've reached the end of the table 4.70 - // without finding the expected interface, so throw an exception 4.71 - Label throw_icce; 4.72 - __ bpr(Assembler::rc_z, false, Assembler::pn, L1, throw_icce); 4.73 - __ delayed()->cmp(G5_interface, L1); 4.74 - __ brx(Assembler::notEqual, true, Assembler::pn, search); 4.75 - __ delayed()->add(L0, itableOffsetEntry::size() * wordSize, L0); 4.76 - 4.77 - // entry found and L0 points to it, move offset of vtable for interface into L0 4.78 - __ ld(L0, base + itableOffsetEntry::offset_offset_in_bytes(), L0); 4.79 - 4.80 - // Compute itableMethodEntry and get methodOop(G5_method) and entrypoint(L0) for compiler 4.81 - const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes(); 4.82 - __ add(G3_klassOop, L0, L1); 4.83 - __ ld_ptr(L1, method_offset, G5_method); 4.84 + Register L5_method = L5; 4.85 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 4.86 + G3_klassOop, G5_interface, itable_index, 4.87 + // outputs: method, scan temp. reg 4.88 + L5_method, L2, L3, 4.89 + throw_icce); 4.90 4.91 #ifndef PRODUCT 4.92 if (DebugVtables) { 4.93 Label L01; 4.94 - __ ld_ptr(L1, method_offset, G5_method); 4.95 - __ bpr(Assembler::rc_nz, false, Assembler::pt, G5_method, L01); 4.96 + __ bpr(Assembler::rc_nz, false, Assembler::pt, L5_method, L01); 4.97 __ delayed()->nop(); 4.98 __ stop("methodOop is null"); 4.99 __ bind(L01); 4.100 - __ verify_oop(G5_method); 4.101 + __ verify_oop(L5_method); 4.102 } 4.103 #endif 4.104 4.105 // If the following load is through a NULL pointer, we'll take an OS 4.106 // exception that should translate into an AbstractMethodError. We need the 4.107 // window count to be correct at that time. 4.108 - __ restore(); // Restore registers BEFORE the AME point 4.109 + __ restore(L5_method, 0, G5_method); 4.110 + // Restore registers *before* the AME point. 4.111 4.112 address ame_addr = __ pc(); // if the vtable entry is null, the method is abstract 4.113 __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch); 4.114 @@ -225,6 +201,12 @@ 4.115 4.116 masm->flush(); 4.117 4.118 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 4.119 + tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", 4.120 + itable_index, s->entry_point(), 4.121 + (int)(s->code_end() - s->entry_point()), 4.122 + (int)(s->code_end() - __ pc())); 4.123 + } 4.124 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 4.125 4.126 s->set_exception_points(npe_addr, ame_addr); 4.127 @@ -243,8 +225,7 @@ 4.128 (UseCompressedOops ? 2*BytesPerInstWord : 0); 4.129 return basic + slop; 4.130 } else { 4.131 - // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore 4.132 - const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord + 4.133 + const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + 4.134 // shift;add for load_klass 4.135 (UseCompressedOops ? 2*BytesPerInstWord : 0); 4.136 return (basic + slop);
5.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Wed Mar 04 09:58:39 2009 -0800 5.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Fri Mar 06 21:36:50 2009 -0800 5.3 @@ -7076,6 +7076,81 @@ 5.4 } 5.5 5.6 5.7 +// Look up the method for a megamorphic invokeinterface call. 5.8 +// The target method is determined by <intf_klass, itable_index>. 5.9 +// The receiver klass is in recv_klass. 5.10 +// On success, the result will be in method_result, and execution falls through. 5.11 +// On failure, execution transfers to the given label. 5.12 +void MacroAssembler::lookup_interface_method(Register recv_klass, 5.13 + Register intf_klass, 5.14 + RegisterConstant itable_index, 5.15 + Register method_result, 5.16 + Register scan_temp, 5.17 + Label& L_no_such_interface) { 5.18 + assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); 5.19 + assert(itable_index.is_constant() || itable_index.as_register() == method_result, 5.20 + "caller must use same register for non-constant itable index as for method"); 5.21 + 5.22 + // Compute start of first itableOffsetEntry (which is at the end of the vtable) 5.23 + int vtable_base = instanceKlass::vtable_start_offset() * wordSize; 5.24 + int itentry_off = itableMethodEntry::method_offset_in_bytes(); 5.25 + int scan_step = itableOffsetEntry::size() * wordSize; 5.26 + int vte_size = vtableEntry::size() * wordSize; 5.27 + Address::ScaleFactor times_vte_scale = Address::times_ptr; 5.28 + assert(vte_size == wordSize, "else adjust times_vte_scale"); 5.29 + 5.30 + movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize)); 5.31 + 5.32 + // %%% Could store the aligned, prescaled offset in the klassoop. 5.33 + lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); 5.34 + if (HeapWordsPerLong > 1) { 5.35 + // Round up to align_object_offset boundary 5.36 + // see code for instanceKlass::start_of_itable! 5.37 + round_to(scan_temp, BytesPerLong); 5.38 + } 5.39 + 5.40 + // Adjust recv_klass by scaled itable_index, so we can free itable_index. 5.41 + assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); 5.42 + lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); 5.43 + 5.44 + // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { 5.45 + // if (scan->interface() == intf) { 5.46 + // result = (klass + scan->offset() + itable_index); 5.47 + // } 5.48 + // } 5.49 + Label search, found_method; 5.50 + 5.51 + for (int peel = 1; peel >= 0; peel--) { 5.52 + movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes())); 5.53 + cmpptr(intf_klass, method_result); 5.54 + 5.55 + if (peel) { 5.56 + jccb(Assembler::equal, found_method); 5.57 + } else { 5.58 + jccb(Assembler::notEqual, search); 5.59 + // (invert the test to fall through to found_method...) 5.60 + } 5.61 + 5.62 + if (!peel) break; 5.63 + 5.64 + bind(search); 5.65 + 5.66 + // Check that the previous entry is non-null. A null entry means that 5.67 + // the receiver class doesn't implement the interface, and wasn't the 5.68 + // same as when the caller was compiled. 5.69 + testptr(method_result, method_result); 5.70 + jcc(Assembler::zero, L_no_such_interface); 5.71 + addptr(scan_temp, scan_step); 5.72 + } 5.73 + 5.74 + bind(found_method); 5.75 + 5.76 + // Got a hit. 5.77 + movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); 5.78 + movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); 5.79 +} 5.80 + 5.81 + 5.82 void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { 5.83 ucomisd(dst, as_Address(src)); 5.84 }
6.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Wed Mar 04 09:58:39 2009 -0800 6.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Fri Mar 06 21:36:50 2009 -0800 6.3 @@ -1765,6 +1765,14 @@ 6.4 ); 6.5 void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); 6.6 6.7 + // interface method calling 6.8 + void lookup_interface_method(Register recv_klass, 6.9 + Register intf_klass, 6.10 + RegisterConstant itable_index, 6.11 + Register method_result, 6.12 + Register scan_temp, 6.13 + Label& no_such_interface); 6.14 + 6.15 //---- 6.16 void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0 6.17
7.1 --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Mar 04 09:58:39 2009 -0800 7.2 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Mar 06 21:36:50 2009 -0800 7.3 @@ -3055,35 +3055,44 @@ 7.4 // profile this call 7.5 __ profile_virtual_call(rdx, rsi, rdi); 7.6 7.7 - __ mov(rdi, rdx); // Save klassOop in rdi 7.8 - 7.9 - // Compute start of first itableOffsetEntry (which is at the end of the vtable) 7.10 - const int base = instanceKlass::vtable_start_offset() * wordSize; 7.11 - assert(vtableEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below"); 7.12 - __ movl(rsi, Address(rdx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable 7.13 - __ lea(rdx, Address(rdx, rsi, Address::times_4, base)); 7.14 - if (HeapWordsPerLong > 1) { 7.15 - // Round up to align_object_offset boundary 7.16 - __ round_to(rdx, BytesPerLong); 7.17 - } 7.18 - 7.19 - Label entry, search, interface_ok; 7.20 - 7.21 - __ jmpb(entry); 7.22 - __ bind(search); 7.23 - __ addptr(rdx, itableOffsetEntry::size() * wordSize); 7.24 - 7.25 - __ bind(entry); 7.26 - 7.27 - // Check that the entry is non-null. A null entry means that the receiver 7.28 - // class doesn't implement the interface, and wasn't the same as the 7.29 - // receiver class checked when the interface was resolved. 7.30 - __ push(rdx); 7.31 - __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); 7.32 - __ testptr(rdx, rdx); 7.33 - __ jcc(Assembler::notZero, interface_ok); 7.34 + Label no_such_interface, no_such_method; 7.35 + 7.36 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 7.37 + rdx, rax, rbx, 7.38 + // outputs: method, scan temp. reg 7.39 + rbx, rsi, 7.40 + no_such_interface); 7.41 + 7.42 + // rbx,: methodOop to call 7.43 + // rcx: receiver 7.44 + // Check for abstract method error 7.45 + // Note: This should be done more efficiently via a throw_abstract_method_error 7.46 + // interpreter entry point and a conditional jump to it in case of a null 7.47 + // method. 7.48 + __ testptr(rbx, rbx); 7.49 + __ jcc(Assembler::zero, no_such_method); 7.50 + 7.51 + // do the call 7.52 + // rcx: receiver 7.53 + // rbx,: methodOop 7.54 + __ jump_from_interpreted(rbx, rdx); 7.55 + __ should_not_reach_here(); 7.56 + 7.57 + // exception handling code follows... 7.58 + // note: must restore interpreter registers to canonical 7.59 + // state for exception handling to work correctly! 7.60 + 7.61 + __ bind(no_such_method); 7.62 // throw exception 7.63 - __ pop(rdx); // pop saved register first. 7.64 + __ pop(rbx); // pop return address (pushed by prepare_invoke) 7.65 + __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) 7.66 + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 7.67 + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); 7.68 + // the call_VM checks for exception, so we should never return here. 7.69 + __ should_not_reach_here(); 7.70 + 7.71 + __ bind(no_such_interface); 7.72 + // throw exception 7.73 __ pop(rbx); // pop return address (pushed by prepare_invoke) 7.74 __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) 7.75 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 7.76 @@ -3091,42 +3100,6 @@ 7.77 InterpreterRuntime::throw_IncompatibleClassChangeError)); 7.78 // the call_VM checks for exception, so we should never return here. 7.79 __ should_not_reach_here(); 7.80 - __ bind(interface_ok); 7.81 - 7.82 - __ pop(rdx); 7.83 - 7.84 - __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); 7.85 - __ jcc(Assembler::notEqual, search); 7.86 - 7.87 - __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes())); 7.88 - __ addptr(rdx, rdi); // Add offset to klassOop 7.89 - assert(itableMethodEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below"); 7.90 - __ movptr(rbx, Address(rdx, rbx, Address::times_ptr)); 7.91 - // rbx,: methodOop to call 7.92 - // rcx: receiver 7.93 - // Check for abstract method error 7.94 - // Note: This should be done more efficiently via a throw_abstract_method_error 7.95 - // interpreter entry point and a conditional jump to it in case of a null 7.96 - // method. 7.97 - { Label L; 7.98 - __ testptr(rbx, rbx); 7.99 - __ jcc(Assembler::notZero, L); 7.100 - // throw exception 7.101 - // note: must restore interpreter registers to canonical 7.102 - // state for exception handling to work correctly! 7.103 - __ pop(rbx); // pop return address (pushed by prepare_invoke) 7.104 - __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) 7.105 - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 7.106 - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); 7.107 - // the call_VM checks for exception, so we should never return here. 7.108 - __ should_not_reach_here(); 7.109 - __ bind(L); 7.110 - } 7.111 - 7.112 - // do the call 7.113 - // rcx: receiver 7.114 - // rbx,: methodOop 7.115 - __ jump_from_interpreted(rbx, rdx); 7.116 } 7.117 7.118 //----------------------------------------------------------------------------------------------------
8.1 --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Mar 04 09:58:39 2009 -0800 8.2 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Mar 06 21:36:50 2009 -0800 8.3 @@ -3010,97 +3010,55 @@ 8.4 // profile this call 8.5 __ profile_virtual_call(rdx, r13, r14); 8.6 8.7 - __ mov(r14, rdx); // Save klassOop in r14 8.8 - 8.9 - // Compute start of first itableOffsetEntry (which is at the end of 8.10 - // the vtable) 8.11 - const int base = instanceKlass::vtable_start_offset() * wordSize; 8.12 - // Get length of vtable 8.13 - assert(vtableEntry::size() * wordSize == 8, 8.14 - "adjust the scaling in the code below"); 8.15 - __ movl(r13, Address(rdx, 8.16 - instanceKlass::vtable_length_offset() * wordSize)); 8.17 - __ lea(rdx, Address(rdx, r13, Address::times_8, base)); 8.18 - 8.19 - if (HeapWordsPerLong > 1) { 8.20 - // Round up to align_object_offset boundary 8.21 - __ round_to(rdx, BytesPerLong); 8.22 - } 8.23 - 8.24 - Label entry, search, interface_ok; 8.25 - 8.26 - __ jmpb(entry); 8.27 - __ bind(search); 8.28 - __ addptr(rdx, itableOffsetEntry::size() * wordSize); 8.29 - 8.30 - __ bind(entry); 8.31 - 8.32 - // Check that the entry is non-null. A null entry means that the 8.33 - // receiver class doesn't implement the interface, and wasn't the 8.34 - // same as the receiver class checked when the interface was 8.35 - // resolved. 8.36 - __ push(rdx); 8.37 - __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); 8.38 - __ testptr(rdx, rdx); 8.39 - __ jcc(Assembler::notZero, interface_ok); 8.40 + Label no_such_interface, no_such_method; 8.41 + 8.42 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 8.43 + rdx, rax, rbx, 8.44 + // outputs: method, scan temp. reg 8.45 + rbx, r13, 8.46 + no_such_interface); 8.47 + 8.48 + // rbx,: methodOop to call 8.49 + // rcx: receiver 8.50 + // Check for abstract method error 8.51 + // Note: This should be done more efficiently via a throw_abstract_method_error 8.52 + // interpreter entry point and a conditional jump to it in case of a null 8.53 + // method. 8.54 + __ testptr(rbx, rbx); 8.55 + __ jcc(Assembler::zero, no_such_method); 8.56 + 8.57 + // do the call 8.58 + // rcx: receiver 8.59 + // rbx,: methodOop 8.60 + __ jump_from_interpreted(rbx, rdx); 8.61 + __ should_not_reach_here(); 8.62 + 8.63 + // exception handling code follows... 8.64 + // note: must restore interpreter registers to canonical 8.65 + // state for exception handling to work correctly! 8.66 + 8.67 + __ bind(no_such_method); 8.68 // throw exception 8.69 - __ pop(rdx); // pop saved register first. 8.70 - __ pop(rbx); // pop return address (pushed by prepare_invoke) 8.71 - __ restore_bcp(); // r13 must be correct for exception handler (was 8.72 - // destroyed) 8.73 - __ restore_locals(); // make sure locals pointer is correct as well 8.74 - // (was destroyed) 8.75 + __ pop(rbx); // pop return address (pushed by prepare_invoke) 8.76 + __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) 8.77 + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 8.78 + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); 8.79 + // the call_VM checks for exception, so we should never return here. 8.80 + __ should_not_reach_here(); 8.81 + 8.82 + __ bind(no_such_interface); 8.83 + // throw exception 8.84 + __ pop(rbx); // pop return address (pushed by prepare_invoke) 8.85 + __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) 8.86 + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 8.87 __ call_VM(noreg, CAST_FROM_FN_PTR(address, 8.88 InterpreterRuntime::throw_IncompatibleClassChangeError)); 8.89 // the call_VM checks for exception, so we should never return here. 8.90 __ should_not_reach_here(); 8.91 - __ bind(interface_ok); 8.92 - 8.93 - __ pop(rdx); 8.94 - 8.95 - __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); 8.96 - __ jcc(Assembler::notEqual, search); 8.97 - 8.98 - __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes())); 8.99 - 8.100 - __ addptr(rdx, r14); // Add offset to klassOop 8.101 - assert(itableMethodEntry::size() * wordSize == 8, 8.102 - "adjust the scaling in the code below"); 8.103 - __ movptr(rbx, Address(rdx, rbx, Address::times_8)); 8.104 - // rbx: methodOop to call 8.105 - // rcx: receiver 8.106 - // Check for abstract method error 8.107 - // Note: This should be done more efficiently via a 8.108 - // throw_abstract_method_error interpreter entry point and a 8.109 - // conditional jump to it in case of a null method. 8.110 - { 8.111 - Label L; 8.112 - __ testptr(rbx, rbx); 8.113 - __ jcc(Assembler::notZero, L); 8.114 - // throw exception 8.115 - // note: must restore interpreter registers to canonical 8.116 - // state for exception handling to work correctly! 8.117 - __ pop(rbx); // pop return address (pushed by prepare_invoke) 8.118 - __ restore_bcp(); // r13 must be correct for exception handler 8.119 - // (was destroyed) 8.120 - __ restore_locals(); // make sure locals pointer is correct as 8.121 - // well (was destroyed) 8.122 - __ call_VM(noreg, 8.123 - CAST_FROM_FN_PTR(address, 8.124 - InterpreterRuntime::throw_AbstractMethodError)); 8.125 - // the call_VM checks for exception, so we should never return here. 8.126 - __ should_not_reach_here(); 8.127 - __ bind(L); 8.128 - } 8.129 - 8.130 - __ movptr(rcx, Address(rbx, methodOopDesc::interpreter_entry_offset())); 8.131 - 8.132 - // do the call 8.133 - // rcx: receiver 8.134 - // rbx: methodOop 8.135 - __ jump_from_interpreted(rbx, rdx); 8.136 + return; 8.137 } 8.138 8.139 + 8.140 //----------------------------------------------------------------------------- 8.141 // Allocation 8.142
9.1 --- a/src/cpu/x86/vm/vtableStubs_x86_32.cpp Wed Mar 04 09:58:39 2009 -0800 9.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp Fri Mar 06 21:36:50 2009 -0800 9.3 @@ -34,10 +34,16 @@ 9.4 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index); 9.5 #endif 9.6 9.7 -// used by compiler only; may use only caller saved registers rax, rbx, rcx. 9.8 -// rdx holds first int arg, rsi, rdi, rbp are callee-save & must be preserved. 9.9 -// Leave receiver in rcx; required behavior when +OptoArgsInRegisters 9.10 -// is modifed to put first oop in rcx. 9.11 +// These stubs are used by the compiler only. 9.12 +// Argument registers, which must be preserved: 9.13 +// rcx - receiver (always first argument) 9.14 +// rdx - second argument (if any) 9.15 +// Other registers that might be usable: 9.16 +// rax - inline cache register (is interface for itable stub) 9.17 +// rbx - method (used when calling out to interpreter) 9.18 +// Available now, but may become callee-save at some point: 9.19 +// rsi, rdi 9.20 +// Note that rax and rdx are also used for return values. 9.21 // 9.22 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { 9.23 const int i486_code_length = VtableStub::pd_code_size_limit(true); 9.24 @@ -94,16 +100,25 @@ 9.25 __ jmp( Address(method, methodOopDesc::from_compiled_offset())); 9.26 9.27 masm->flush(); 9.28 + 9.29 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 9.30 + tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", 9.31 + vtable_index, s->entry_point(), 9.32 + (int)(s->code_end() - s->entry_point()), 9.33 + (int)(s->code_end() - __ pc())); 9.34 + } 9.35 + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 9.36 + 9.37 s->set_exception_points(npe_addr, ame_addr); 9.38 return s; 9.39 } 9.40 9.41 9.42 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) { 9.43 +VtableStub* VtableStubs::create_itable_stub(int itable_index) { 9.44 // Note well: pd_code_size_limit is the absolute minimum we can get away with. If you 9.45 // add code here, bump the code stub size returned by pd_code_size_limit! 9.46 const int i486_code_length = VtableStub::pd_code_size_limit(false); 9.47 - VtableStub* s = new(i486_code_length) VtableStub(false, vtable_index); 9.48 + VtableStub* s = new(i486_code_length) VtableStub(false, itable_index); 9.49 ResourceMark rm; 9.50 CodeBuffer cb(s->entry_point(), i486_code_length); 9.51 MacroAssembler* masm = new MacroAssembler(&cb); 9.52 @@ -123,50 +138,19 @@ 9.53 9.54 // get receiver klass (also an implicit null-check) 9.55 address npe_addr = __ pc(); 9.56 - __ movptr(rbx, Address(rcx, oopDesc::klass_offset_in_bytes())); 9.57 + __ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes())); 9.58 9.59 - __ mov(rsi, rbx); // Save klass in free register 9.60 - // Most registers are in use, so save a few 9.61 - __ push(rdx); 9.62 - // compute itable entry offset (in words) 9.63 - const int base = instanceKlass::vtable_start_offset() * wordSize; 9.64 - assert(vtableEntry::size() * wordSize == 4, "adjust the scaling in the code below"); 9.65 - __ movl(rdx, Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable 9.66 - __ lea(rbx, Address(rbx, rdx, Address::times_ptr, base)); 9.67 - if (HeapWordsPerLong > 1) { 9.68 - // Round up to align_object_offset boundary 9.69 - __ round_to(rbx, BytesPerLong); 9.70 - } 9.71 - 9.72 - Label hit, next, entry, throw_icce; 9.73 - 9.74 - __ jmpb(entry); 9.75 - 9.76 - __ bind(next); 9.77 - __ addptr(rbx, itableOffsetEntry::size() * wordSize); 9.78 - 9.79 - __ bind(entry); 9.80 - 9.81 - // If the entry is NULL then we've reached the end of the table 9.82 - // without finding the expected interface, so throw an exception 9.83 - __ movptr(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); 9.84 - __ testptr(rdx, rdx); 9.85 - __ jcc(Assembler::zero, throw_icce); 9.86 - __ cmpptr(rax, rdx); 9.87 - __ jcc(Assembler::notEqual, next); 9.88 - 9.89 - // We found a hit, move offset into rbx, 9.90 - __ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); 9.91 - 9.92 - // Compute itableMethodEntry. 9.93 - const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes(); 9.94 + // Most registers are in use; we'll use rax, rbx, rsi, rdi 9.95 + // (If we need to make rsi, rdi callee-save, do a push/pop here.) 9.96 + const Register method = rbx; 9.97 + Label throw_icce; 9.98 9.99 // Get methodOop and entrypoint for compiler 9.100 - const Register method = rbx; 9.101 - __ movptr(method, Address(rsi, rdx, Address::times_1, method_offset)); 9.102 - 9.103 - // Restore saved register, before possible trap. 9.104 - __ pop(rdx); 9.105 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 9.106 + rsi, rax, itable_index, 9.107 + // outputs: method, scan temp. reg 9.108 + method, rdi, 9.109 + throw_icce); 9.110 9.111 // method (rbx): methodOop 9.112 // rcx: receiver 9.113 @@ -187,12 +171,15 @@ 9.114 __ jmp(Address(method, methodOopDesc::from_compiled_offset())); 9.115 9.116 __ bind(throw_icce); 9.117 - // Restore saved register 9.118 - __ pop(rdx); 9.119 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); 9.120 - 9.121 masm->flush(); 9.122 9.123 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 9.124 + tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", 9.125 + itable_index, s->entry_point(), 9.126 + (int)(s->code_end() - s->entry_point()), 9.127 + (int)(s->code_end() - __ pc())); 9.128 + } 9.129 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 9.130 9.131 s->set_exception_points(npe_addr, ame_addr); 9.132 @@ -207,7 +194,7 @@ 9.133 return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0); 9.134 } else { 9.135 // Itable stub size 9.136 - return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0); 9.137 + return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0); 9.138 } 9.139 } 9.140
10.1 --- a/src/cpu/x86/vm/vtableStubs_x86_64.cpp Wed Mar 04 09:58:39 2009 -0800 10.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_64.cpp Fri Mar 06 21:36:50 2009 -0800 10.3 @@ -98,17 +98,26 @@ 10.4 __ jmp( Address(rbx, methodOopDesc::from_compiled_offset())); 10.5 10.6 __ flush(); 10.7 + 10.8 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 10.9 + tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", 10.10 + vtable_index, s->entry_point(), 10.11 + (int)(s->code_end() - s->entry_point()), 10.12 + (int)(s->code_end() - __ pc())); 10.13 + } 10.14 + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 10.15 + 10.16 s->set_exception_points(npe_addr, ame_addr); 10.17 return s; 10.18 } 10.19 10.20 10.21 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) { 10.22 +VtableStub* VtableStubs::create_itable_stub(int itable_index) { 10.23 // Note well: pd_code_size_limit is the absolute minimum we can get 10.24 // away with. If you add code here, bump the code stub size 10.25 // returned by pd_code_size_limit! 10.26 const int amd64_code_length = VtableStub::pd_code_size_limit(false); 10.27 - VtableStub* s = new(amd64_code_length) VtableStub(false, vtable_index); 10.28 + VtableStub* s = new(amd64_code_length) VtableStub(false, itable_index); 10.29 ResourceMark rm; 10.30 CodeBuffer cb(s->entry_point(), amd64_code_length); 10.31 MacroAssembler* masm = new MacroAssembler(&cb); 10.32 @@ -131,68 +140,28 @@ 10.33 // get receiver klass (also an implicit null-check) 10.34 address npe_addr = __ pc(); 10.35 10.36 - __ load_klass(rbx, j_rarg0); 10.37 + // Most registers are in use; we'll use rax, rbx, r10, r11 10.38 + // (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them) 10.39 + __ load_klass(r10, j_rarg0); 10.40 10.41 // If we take a trap while this arg is on the stack we will not 10.42 // be able to walk the stack properly. This is not an issue except 10.43 // when there are mistakes in this assembly code that could generate 10.44 // a spurious fault. Ask me how I know... 10.45 10.46 - __ push(j_rarg1); // Most registers are in use, so save one 10.47 - 10.48 - // compute itable entry offset (in words) 10.49 - const int base = instanceKlass::vtable_start_offset() * wordSize; 10.50 - assert(vtableEntry::size() * wordSize == 8, 10.51 - "adjust the scaling in the code below"); 10.52 - // Get length of vtable 10.53 - __ movl(j_rarg1, 10.54 - Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); 10.55 - __ lea(rbx, Address(rbx, j_rarg1, Address::times_8, base)); 10.56 - 10.57 - if (HeapWordsPerLong > 1) { 10.58 - // Round up to align_object_offset boundary 10.59 - __ round_to(rbx, BytesPerLong); 10.60 - } 10.61 - Label hit, next, entry, throw_icce; 10.62 - 10.63 - __ jmpb(entry); 10.64 - 10.65 - __ bind(next); 10.66 - __ addptr(rbx, itableOffsetEntry::size() * wordSize); 10.67 - 10.68 - __ bind(entry); 10.69 - 10.70 - // If the entry is NULL then we've reached the end of the table 10.71 - // without finding the expected interface, so throw an exception 10.72 - __ movptr(j_rarg1, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); 10.73 - __ testptr(j_rarg1, j_rarg1); 10.74 - __ jcc(Assembler::zero, throw_icce); 10.75 - __ cmpptr(rax, j_rarg1); 10.76 - __ jccb(Assembler::notEqual, next); 10.77 - 10.78 - // We found a hit, move offset into j_rarg1 10.79 - __ movl(j_rarg1, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); 10.80 - 10.81 - // Compute itableMethodEntry 10.82 - const int method_offset = 10.83 - (itableMethodEntry::size() * wordSize * vtable_index) + 10.84 - itableMethodEntry::method_offset_in_bytes(); 10.85 + const Register method = rbx; 10.86 + Label throw_icce; 10.87 10.88 // Get methodOop and entrypoint for compiler 10.89 - 10.90 - // Get klass pointer again 10.91 - __ load_klass(rax, j_rarg0); 10.92 - 10.93 - const Register method = rbx; 10.94 - __ movptr(method, Address(rax, j_rarg1, Address::times_1, method_offset)); 10.95 - 10.96 - // Restore saved register, before possible trap. 10.97 - __ pop(j_rarg1); 10.98 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 10.99 + r10, rax, itable_index, 10.100 + // outputs: method, scan temp. reg 10.101 + method, r11, 10.102 + throw_icce); 10.103 10.104 // method (rbx): methodOop 10.105 // j_rarg0: receiver 10.106 10.107 - 10.108 #ifdef ASSERT 10.109 if (DebugVtables) { 10.110 Label L2; 10.111 @@ -211,12 +180,16 @@ 10.112 __ jmp(Address(method, methodOopDesc::from_compiled_offset())); 10.113 10.114 __ bind(throw_icce); 10.115 - // Restore saved register 10.116 - __ pop(j_rarg1); 10.117 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); 10.118 10.119 __ flush(); 10.120 10.121 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 10.122 + tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", 10.123 + itable_index, s->entry_point(), 10.124 + (int)(s->code_end() - s->entry_point()), 10.125 + (int)(s->code_end() - __ pc())); 10.126 + } 10.127 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 10.128 10.129 s->set_exception_points(npe_addr, ame_addr); 10.130 @@ -230,7 +203,7 @@ 10.131 (UseCompressedOops ? 16 : 0); // 1 leaq can be 3 bytes + 1 long 10.132 } else { 10.133 // Itable stub size 10.134 - return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0) + 10.135 + return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) + 10.136 (UseCompressedOops ? 32 : 0); // 2 leaqs 10.137 } 10.138 }