# HG changeset patch # User dcubed # Date 1196874000 28800 # Node ID f8236e79048ae164bc348ce99462e754460b23a6 # Parent 92489cdc94d1ad7b1fa668b83e4bfa118247b06b 6664627: Merge changes made only in hotspot 11 forward to jdk 7 Reviewed-by: jcoomes diff -r 92489cdc94d1 -r f8236e79048a src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -2911,6 +2911,7 @@ // These entry points require SharedInfo::stack0 to be set up in non-core builds StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError), false); + StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); StubRoutines::_throw_ArithmeticException_entry = generate_throw_exception("ArithmeticException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_ArithmeticException), true); StubRoutines::_throw_NullPointerException_entry = generate_throw_exception("NullPointerException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException), true); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); diff -r 92489cdc94d1 -r f8236e79048a src/cpu/sparc/vm/vtableStubs_sparc.cpp --- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -175,17 +175,12 @@ // %%%% Could load both offset and interface in one ldx, if they were // in the opposite order. This would save a load. __ ld_ptr(L0, base + itableOffsetEntry::interface_offset_in_bytes(), L1); -#ifdef ASSERT - Label ok; - // Check that entry is non-null and an Oop - __ bpr(Assembler::rc_nz, false, Assembler::pt, L1, ok); - __ delayed()->nop(); - __ stop("null entry point found in itable's offset table"); - __ bind(ok); - __ verify_oop(L1); -#endif // ASSERT - __ cmp(G5_interface, L1); + // If the entry is NULL then we've reached the end of the table + // without finding the expected interface, so throw an exception + Label throw_icce; + __ bpr(Assembler::rc_z, false, Assembler::pn, L1, throw_icce); + __ delayed()->cmp(G5_interface, L1); __ brx(Assembler::notEqual, true, Assembler::pn, search); __ delayed()->add(L0, itableOffsetEntry::size() * wordSize, L0); @@ -223,24 +218,30 @@ __ JMP(G3_scratch, 0); __ delayed()->nop(); + __ bind(throw_icce); + Address icce(G3_scratch, StubRoutines::throw_IncompatibleClassChangeError_entry()); + __ jump_to(icce, 0); + __ delayed()->restore(); + masm->flush(); + + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); + s->set_exception_points(npe_addr, ame_addr); return s; } int VtableStub::pd_code_size_limit(bool is_vtable_stub) { - if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) return 999; + if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) return 1000; else { const int slop = 2*BytesPerInstWord; // sethi;add (needed for long offsets) if (is_vtable_stub) { const int basic = 5*BytesPerInstWord; // ld;ld;ld,jmp,nop return basic + slop; } else { -#ifdef ASSERT - return 999; -#endif // ASSERT - const int basic = 17*BytesPerInstWord; // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore + // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore + const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord; return (basic + slop); } } @@ -252,29 +253,3 @@ const unsigned int icache_line_size = 32; return icache_line_size; } - - -//Reconciliation History -// 1.2 97/12/09 17:13:31 vtableStubs_i486.cpp -// 1.4 98/01/21 19:18:37 vtableStubs_i486.cpp -// 1.5 98/02/13 16:33:55 vtableStubs_i486.cpp -// 1.7 98/03/05 17:17:28 vtableStubs_i486.cpp -// 1.9 98/05/18 09:26:17 vtableStubs_i486.cpp -// 1.10 98/05/26 16:28:13 vtableStubs_i486.cpp -// 1.11 98/05/27 08:51:35 vtableStubs_i486.cpp -// 1.12 98/06/15 15:04:12 vtableStubs_i486.cpp -// 1.13 98/07/28 18:44:22 vtableStubs_i486.cpp -// 1.15 98/08/28 11:31:19 vtableStubs_i486.cpp -// 1.16 98/09/02 12:58:31 vtableStubs_i486.cpp -// 1.17 98/09/04 12:15:52 vtableStubs_i486.cpp -// 1.18 98/11/19 11:55:24 vtableStubs_i486.cpp -// 1.19 99/01/12 14:57:56 vtableStubs_i486.cpp -// 1.20 99/01/19 17:42:52 vtableStubs_i486.cpp -// 1.22 99/01/21 10:29:25 vtableStubs_i486.cpp -// 1.30 99/06/02 15:27:39 vtableStubs_i486.cpp -// 1.26 99/06/24 14:25:07 vtableStubs_i486.cpp -// 1.23 99/02/22 14:37:52 vtableStubs_i486.cpp -// 1.28 99/06/29 18:06:17 vtableStubs_i486.cpp -// 1.29 99/07/22 17:03:44 vtableStubs_i486.cpp -// 1.30 99/08/11 09:33:27 vtableStubs_i486.cpp -//End diff -r 92489cdc94d1 -r f8236e79048a src/cpu/x86/vm/stubGenerator_x86_32.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -2151,6 +2151,7 @@ // These entry points require SharedInfo::stack0 to be set up in non-core builds // and need to be relocatable, so they each fabricate a RuntimeStub internally. StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError), false); + StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); StubRoutines::_throw_ArithmeticException_entry = generate_throw_exception("ArithmeticException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_ArithmeticException), true); StubRoutines::_throw_NullPointerException_entry = generate_throw_exception("NullPointerException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException), true); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); diff -r 92489cdc94d1 -r f8236e79048a src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -2832,6 +2832,13 @@ throw_AbstractMethodError), false); + StubRoutines::_throw_IncompatibleClassChangeError_entry = + generate_throw_exception("IncompatibleClassChangeError throw_exception", + CAST_FROM_FN_PTR(address, + SharedRuntime:: + throw_IncompatibleClassChangeError), + false); + StubRoutines::_throw_ArithmeticException_entry = generate_throw_exception("ArithmeticException throw_exception", CAST_FROM_FN_PTR(address, diff -r 92489cdc94d1 -r f8236e79048a src/cpu/x86/vm/vtableStubs_x86_32.cpp --- a/src/cpu/x86/vm/vtableStubs_x86_32.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -138,29 +138,21 @@ __ round_to(rbx, BytesPerLong); } - Label hit, next, entry; + Label hit, next, entry, throw_icce; - __ jmp(entry); + __ jmpb(entry); __ bind(next); __ addl(rbx, itableOffsetEntry::size() * wordSize); __ bind(entry); -#ifdef ASSERT - // Check that the entry is non-null - if (DebugVtables) { - Label L; - __ pushl(rbx); - __ movl(rbx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); - __ testl(rbx, rbx); - __ jcc(Assembler::notZero, L); - __ stop("null entry point found in itable's offset table"); - __ bind(L); - __ popl(rbx); - } -#endif - __ cmpl(rax, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); + // If the entry is NULL then we've reached the end of the table + // without finding the expected interface, so throw an exception + __ movl(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); + __ testl(rdx, rdx); + __ jcc(Assembler::zero, throw_icce); + __ cmpl(rax, rdx); __ jcc(Assembler::notEqual, next); // We found a hit, move offset into rbx, @@ -194,7 +186,15 @@ address ame_addr = __ pc(); __ jmp(Address(method, methodOopDesc::from_compiled_offset())); + __ bind(throw_icce); + // Restore saved register + __ popl(rdx); + __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); + masm->flush(); + + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); + s->set_exception_points(npe_addr, ame_addr); return s; } @@ -207,7 +207,7 @@ return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0); } else { // Itable stub size - return (DebugVtables ? 140 : 55) + (CountCompiledCalls ? 6 : 0); + return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0); } } diff -r 92489cdc94d1 -r f8236e79048a src/cpu/x86/vm/vtableStubs_x86_64.cpp --- a/src/cpu/x86/vm/vtableStubs_x86_64.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/cpu/x86/vm/vtableStubs_x86_64.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -153,7 +153,7 @@ // Round up to align_object_offset boundary __ round_to_q(rbx, BytesPerLong); } - Label hit, next, entry; + Label hit, next, entry, throw_icce; __ jmpb(entry); @@ -162,22 +162,13 @@ __ bind(entry); -#ifdef ASSERT - // Check that the entry is non-null - if (DebugVtables) { - Label L; - __ pushq(rbx); - __ movq(rbx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); - __ testq(rbx, rbx); - __ jcc(Assembler::notZero, L); - __ stop("null entry point found in itable's offset table"); - __ bind(L); - __ popq(rbx); - } -#endif - - __ cmpq(rax, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); - __ jcc(Assembler::notEqual, next); + // If the entry is NULL then we've reached the end of the table + // without finding the expected interface, so throw an exception + __ movq(j_rarg1, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); + __ testq(j_rarg1, j_rarg1); + __ jcc(Assembler::zero, throw_icce); + __ cmpq(rax, j_rarg1); + __ jccb(Assembler::notEqual, next); // We found a hit, move offset into j_rarg1 __ movl(j_rarg1, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); @@ -203,23 +194,31 @@ #ifdef ASSERT - if (DebugVtables) { - Label L2; - __ cmpq(method, (int)NULL); - __ jcc(Assembler::equal, L2); - __ cmpq(Address(method, methodOopDesc::from_compiled_offset()), (int)NULL_WORD); - __ jcc(Assembler::notZero, L2); - __ stop("compiler entrypoint is null"); - __ bind(L2); - } + if (DebugVtables) { + Label L2; + __ cmpq(method, (int)NULL); + __ jcc(Assembler::equal, L2); + __ cmpq(Address(method, methodOopDesc::from_compiled_offset()), (int)NULL_WORD); + __ jcc(Assembler::notZero, L2); + __ stop("compiler entrypoint is null"); + __ bind(L2); + } #endif // ASSERT - // rbx: methodOop - // j_rarg0: receiver - address ame_addr = __ pc(); - __ jmp(Address(method, methodOopDesc::from_compiled_offset())); + // rbx: methodOop + // j_rarg0: receiver + address ame_addr = __ pc(); + __ jmp(Address(method, methodOopDesc::from_compiled_offset())); + + __ bind(throw_icce); + // Restore saved register + __ popq(j_rarg1); + __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); __ flush(); + + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); + s->set_exception_points(npe_addr, ame_addr); return s; } @@ -230,7 +229,7 @@ return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0); } else { // Itable stub size - return (DebugVtables ? 636 : 64) + (CountCompiledCalls ? 13 : 0); + return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0); } } diff -r 92489cdc94d1 -r f8236e79048a src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/share/vm/oops/klassVtable.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -735,7 +735,7 @@ } } - // This lenght of the itable was either zero, or it has not yet been initialized. + // The length of the itable was either zero, or it has not yet been initialized. _table_offset = 0; _size_offset_table = 0; _size_method_table = 0; @@ -870,16 +870,19 @@ // Initialization void klassItable::initialize_itable(bool checkconstraints, TRAPS) { - // Cannot be setup doing bootstrapping - if (Universe::is_bootstrapping()) return; + // Cannot be setup doing bootstrapping, interfaces don't have + // itables, and klass with only ones entry have empty itables + if (Universe::is_bootstrapping() || + _klass->is_interface() || + _klass->itable_length() == itableOffsetEntry::size()) return; - int num_interfaces = nof_interfaces(); + // There's alway an extra itable entry so we can null-terminate it. + guarantee(size_offset_table() >= 1, "too small"); + int num_interfaces = size_offset_table() - 1; if (num_interfaces > 0) { - if (TraceItables) tty->print_cr("%3d: Initializing itables for %s", ++initialize_count, _klass->name()->as_C_string()); + if (TraceItables) tty->print_cr("%3d: Initializing itables for %s", ++initialize_count, + _klass->name()->as_C_string()); - // In debug mode, we got an extra NULL/NULL entry - debug_only(num_interfaces--); - assert(num_interfaces > 0, "to few interfaces in offset itable"); // Interate through all interfaces int i; @@ -890,12 +893,10 @@ initialize_itable_for_interface(ioe->offset(), interf_h, checkconstraints, CHECK); } -#ifdef ASSERT - // Check that the last entry is empty - itableOffsetEntry* ioe = offset_entry(i); - assert(ioe->interface_klass() == NULL && ioe->offset() == 0, "terminator entry missing"); -#endif } + // Check that the last entry is empty + itableOffsetEntry* ioe = offset_entry(size_offset_table() - 1); + guarantee(ioe->interface_klass() == NULL && ioe->offset() == 0, "terminator entry missing"); } @@ -972,7 +973,7 @@ } } -// Update entry for specic methodOop +// Update entry for specific methodOop void klassItable::initialize_with_method(methodOop m) { itableMethodEntry* ime = method_entry(0); for(int i = 0; i < _size_method_table; i++) { @@ -1085,12 +1086,8 @@ CountInterfacesClosure cic; visit_all_interfaces(transitive_interfaces(), &cic); - // Add one extra entry in debug mode, so we can null-terminate the table - int nof_methods = cic.nof_methods(); - int nof_interfaces = cic.nof_interfaces(); - debug_only(if (nof_interfaces > 0) nof_interfaces++); - - int itable_size = calc_itable_size(nof_interfaces, nof_methods); + // There's alway an extra itable entry so we can null-terminate it. + int itable_size = calc_itable_size(cic.nof_interfaces() + 1, cic.nof_methods()); // Statistics update_stats(itable_size * HeapWordSize); @@ -1110,8 +1107,8 @@ int nof_methods = cic.nof_methods(); int nof_interfaces = cic.nof_interfaces(); - // Add one extra entry in debug mode, so we can null-terminate the table - debug_only(if (nof_interfaces > 0) nof_interfaces++); + // Add one extra entry so we can null-terminate the table + nof_interfaces++; assert(compute_itable_size(objArrayHandle(klass->transitive_interfaces())) == calc_itable_size(nof_interfaces, nof_methods), diff -r 92489cdc94d1 -r f8236e79048a src/share/vm/oops/klassVtable.hpp --- a/src/share/vm/oops/klassVtable.hpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/share/vm/oops/klassVtable.hpp Wed Dec 05 09:00:00 2007 -0800 @@ -259,7 +259,7 @@ itableMethodEntry* method_entry(int i) { assert(0 <= i && i <= _size_method_table, "index out of bounds"); return &((itableMethodEntry*)method_start())[i]; } - int nof_interfaces() { return _size_offset_table; } + int size_offset_table() { return _size_offset_table; } // Initialization void initialize_itable(bool checkconstraints, TRAPS); diff -r 92489cdc94d1 -r f8236e79048a src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/share/vm/runtime/sharedRuntime.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -467,6 +467,11 @@ throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_AbstractMethodError()); JRT_END +JRT_ENTRY(void, SharedRuntime::throw_IncompatibleClassChangeError(JavaThread* thread)) + // These errors occur only at call sites + throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_IncompatibleClassChangeError(), "vtable stub"); +JRT_END + JRT_ENTRY(void, SharedRuntime::throw_ArithmeticException(JavaThread* thread)) throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArithmeticException(), "/ by zero"); JRT_END diff -r 92489cdc94d1 -r f8236e79048a src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/share/vm/runtime/sharedRuntime.hpp Wed Dec 05 09:00:00 2007 -0800 @@ -104,6 +104,7 @@ STACK_OVERFLOW }; static void throw_AbstractMethodError(JavaThread* thread); + static void throw_IncompatibleClassChangeError(JavaThread* thread); static void throw_ArithmeticException(JavaThread* thread); static void throw_NullPointerException(JavaThread* thread); static void throw_NullPointerException_at_call(JavaThread* thread); diff -r 92489cdc94d1 -r f8236e79048a src/share/vm/runtime/stubRoutines.cpp --- a/src/share/vm/runtime/stubRoutines.cpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/share/vm/runtime/stubRoutines.cpp Wed Dec 05 09:00:00 2007 -0800 @@ -40,6 +40,7 @@ address StubRoutines::_catch_exception_entry = NULL; address StubRoutines::_forward_exception_entry = NULL; address StubRoutines::_throw_AbstractMethodError_entry = NULL; +address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL; address StubRoutines::_throw_ArithmeticException_entry = NULL; address StubRoutines::_throw_NullPointerException_entry = NULL; address StubRoutines::_throw_NullPointerException_at_call_entry = NULL; diff -r 92489cdc94d1 -r f8236e79048a src/share/vm/runtime/stubRoutines.hpp --- a/src/share/vm/runtime/stubRoutines.hpp Tue Dec 04 16:28:18 2007 -0800 +++ b/src/share/vm/runtime/stubRoutines.hpp Wed Dec 05 09:00:00 2007 -0800 @@ -84,6 +84,7 @@ static address _forward_exception_entry; static address _catch_exception_entry; static address _throw_AbstractMethodError_entry; + static address _throw_IncompatibleClassChangeError_entry; static address _throw_ArithmeticException_entry; static address _throw_NullPointerException_entry; static address _throw_NullPointerException_at_call_entry; @@ -184,6 +185,7 @@ static address forward_exception_entry() { return _forward_exception_entry; } // Implicit exceptions static address throw_AbstractMethodError_entry() { return _throw_AbstractMethodError_entry; } + static address throw_IncompatibleClassChangeError_entry(){ return _throw_IncompatibleClassChangeError_entry; } static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; } static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; } static address throw_NullPointerException_at_call_entry(){ return _throw_NullPointerException_at_call_entry; }