# HG changeset patch # User iveresov # Date 1318759164 25200 # Node ID 11d17c7d2ee6aba2e92d5f2a2ca3003c635ee573 # Parent bc257a801090f9f2443fd50be5a6d7e6cd7520f4# Parent 4bac06a82bc3ec47fa95aa92182d68b22fbc05e5 Merge diff -r bc257a801090 -r 11d17c7d2ee6 src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Fri Oct 14 21:45:37 2011 -0700 +++ b/src/cpu/sparc/vm/sparc.ad Sun Oct 16 02:59:24 2011 -0700 @@ -10476,7 +10476,7 @@ ins_pipe(ialu_reg); %} -instruct countTrailingZerosL(iRegI dst, iRegL src, flagsReg cr) %{ +instruct countTrailingZerosL(iRegIsafe dst, iRegL src, flagsReg cr) %{ predicate(UsePopCountInstruction); // See Matcher::match_rule_supported match(Set dst (CountTrailingZerosL src)); effect(TEMP dst, KILL cr); diff -r bc257a801090 -r 11d17c7d2ee6 src/cpu/x86/vm/frame_x86.cpp --- a/src/cpu/x86/vm/frame_x86.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/cpu/x86/vm/frame_x86.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -232,11 +232,13 @@ void frame::patch_pc(Thread* thread, address pc) { + address* pc_addr = &(((address*) sp())[-1]); if (TracePcPatching) { - tty->print_cr("patch_pc at address" INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "] ", - &((address *)sp())[-1], ((address *)sp())[-1], pc); + tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "] ", + pc_addr, *pc_addr, pc); } - ((address *)sp())[-1] = pc; + assert(_pc == *pc_addr, err_msg("must be: " INTPTR_FORMAT " == " INTPTR_FORMAT, _pc, *pc_addr)); + *pc_addr = pc; _cb = CodeCache::find_blob(pc); address original_pc = nmethod::get_deopt_original_pc(this); if (original_pc != NULL) { @@ -671,4 +673,3 @@ // used to reset the saved FP return fp(); } - diff -r bc257a801090 -r 11d17c7d2ee6 src/cpu/x86/vm/methodHandles_x86.cpp --- a/src/cpu/x86/vm/methodHandles_x86.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -410,8 +410,8 @@ void MethodHandles::RicochetFrame::verify() const { verify_offsets(); - assert(magic_number_1() == MAGIC_NUMBER_1, ""); - assert(magic_number_2() == MAGIC_NUMBER_2, ""); + assert(magic_number_1() == MAGIC_NUMBER_1, err_msg(PTR_FORMAT " == " PTR_FORMAT, magic_number_1(), MAGIC_NUMBER_1)); + assert(magic_number_2() == MAGIC_NUMBER_2, err_msg(PTR_FORMAT " == " PTR_FORMAT, magic_number_2(), MAGIC_NUMBER_2)); if (!Universe::heap()->is_gc_active()) { if (saved_args_layout() != NULL) { assert(saved_args_layout()->is_method(), "must be valid oop"); diff -r bc257a801090 -r 11d17c7d2ee6 src/cpu/x86/vm/methodHandles_x86.hpp --- a/src/cpu/x86/vm/methodHandles_x86.hpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/cpu/x86/vm/methodHandles_x86.hpp Sun Oct 16 02:59:24 2011 -0700 @@ -132,7 +132,10 @@ intptr_t* sender_link() const { return _sender_link; } address sender_pc() const { return _sender_pc; } - intptr_t* extended_sender_sp() const { return saved_args_base(); } + intptr_t* extended_sender_sp() const { + // The extended sender SP is above the current RicochetFrame. + return (intptr_t*) (((address) this) + sizeof(RicochetFrame)); + } intptr_t return_value_slot_number() const { return adapter_conversion_vminfo(conversion()); diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -1165,11 +1165,11 @@ Goto *x = new Goto(block_at(to_bci), to_bci <= from_bci); if (is_profiling()) { compilation()->set_would_profile(true); - } - if (profile_branches()) { - x->set_profiled_method(method()); x->set_profiled_bci(bci()); - x->set_should_profile(true); + if (profile_branches()) { + x->set_profiled_method(method()); + x->set_should_profile(true); + } } append(x); } @@ -1203,9 +1203,9 @@ Goto *goto_node = i->as_Goto(); if (goto_node != NULL) { compilation()->set_would_profile(true); + goto_node->set_profiled_bci(bci()); if (profile_branches()) { goto_node->set_profiled_method(method()); - goto_node->set_profiled_bci(bci()); goto_node->set_should_profile(true); // Find out which successor is used. if (goto_node->default_sux() == tsux) { diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -2493,7 +2493,7 @@ // increment backedge counter if needed CodeEmitInfo* info = state_for(x, state); - increment_backedge_counter(info, info->stack()->bci()); + increment_backedge_counter(info, x->profiled_bci()); CodeEmitInfo* safepoint_info = state_for(x, state); __ safepoint(safepoint_poll_register(), safepoint_info); } diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/c1/c1_LinearScan.cpp --- a/src/share/vm/c1/c1_LinearScan.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/c1/c1_LinearScan.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -2619,6 +2619,24 @@ Location::Type loc_type = float_saved_as_double ? Location::float_in_dbl : Location::normal; VMReg rname = frame_map()->fpu_regname(opr->fpu_regnr()); +#ifndef __SOFTFP__ +#ifndef VM_LITTLE_ENDIAN + if (! float_saved_as_double) { + // On big endian system, we may have an issue if float registers use only + // the low half of the (same) double registers. + // Both the float and the double could have the same regnr but would correspond + // to two different addresses once saved. + + // get next safely (no assertion checks) + VMReg next = VMRegImpl::as_VMReg(1+rname->value()); + if (next->is_reg() && + (next->as_FloatRegister() == rname->as_FloatRegister())) { + // the back-end does use the same numbering for the double and the float + rname = next; // VMReg for the low bits, e.g. the real VMReg for the float + } + } +#endif +#endif LocationValue* sv = new LocationValue(Location::new_reg_loc(loc_type, rname)); scope_values->append(sv); diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/ci/ciEnv.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -473,6 +473,7 @@ } if (require_local) return NULL; + // Not yet loaded into the VM, or not governed by loader constraints. // Make a CI representative for it. return get_unloaded_klass(accessing_klass, name); @@ -498,7 +499,7 @@ bool& is_accessible, ciInstanceKlass* accessor) { EXCEPTION_CONTEXT; - KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); + KlassHandle klass(THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); Symbol* klass_name = NULL; if (klass.is_null()) { // The klass has not been inserted into the constant pool. @@ -785,17 +786,17 @@ // Either the declared holder was not loaded, or the method could // not be found. Create a dummy ciMethod to represent the failed // lookup. - - return get_unloaded_method(declared_holder, - get_symbol(name_sym), - get_symbol(sig_sym)); + ciSymbol* name = get_symbol(name_sym); + ciSymbol* signature = get_symbol(sig_sym); + return get_unloaded_method(declared_holder, name, signature, accessor); } // ------------------------------------------------------------------ // ciEnv::get_fake_invokedynamic_method_impl ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, - int index, Bytecodes::Code bc) { + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor) { // Compare the following logic with InterpreterRuntime::resolve_invokedynamic. assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); @@ -807,9 +808,10 @@ // Call site might not be resolved yet. We could create a real invoker method from the // compiler, but it is simpler to stop the code path here with an unlinked method. if (!is_resolved) { - ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); - ciSymbol* sig_sym = get_symbol(cpool->signature_ref_at(index)); - return get_unloaded_method(mh_klass, ciSymbol::invokeExact_name(), sig_sym); + ciInstanceKlass* holder = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); + ciSymbol* name = ciSymbol::invokeExact_name(); + ciSymbol* signature = get_symbol(cpool->signature_ref_at(index)); + return get_unloaded_method(holder, name, signature, accessor); } // Get the invoker methodOop from the constant pool. @@ -850,9 +852,9 @@ int index, Bytecodes::Code bc, ciInstanceKlass* accessor) { if (bc == Bytecodes::_invokedynamic) { - GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc);) + GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc, accessor);) } else { - GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);) + GUARDED_VM_ENTRY(return get_method_by_index_impl( cpool, index, bc, accessor);) } } diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/ci/ciEnv.hpp --- a/src/share/vm/ci/ciEnv.hpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/ci/ciEnv.hpp Sun Oct 16 02:59:24 2011 -0700 @@ -153,7 +153,8 @@ int method_index, Bytecodes::Code bc, ciInstanceKlass* loading_klass); ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool, - int index, Bytecodes::Code bc); + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor); // Helper methods bool check_klass_accessibility(ciKlass* accessing_klass, @@ -192,13 +193,14 @@ // the result. ciMethod* get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature) { - return _factory->get_unloaded_method(holder, name, signature); + ciSymbol* signature, + ciInstanceKlass* accessor) { + return _factory->get_unloaded_method(holder, name, signature, accessor); } // Get a ciKlass representing an unloaded klass. // Ensures uniqueness of the result. - ciKlass* get_unloaded_klass(ciKlass* accessing_klass, + ciKlass* get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { return _factory->get_unloaded_klass(accessing_klass, name, true); } @@ -224,7 +226,7 @@ // See if we already have an unloaded klass for the given name // or return NULL if not. - ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { + ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { return _factory->get_unloaded_klass(accessing_klass, name, false); } diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/ci/ciMethod.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -148,21 +148,27 @@ // // Unloaded method. ciMethod::ciMethod(ciInstanceKlass* holder, - ciSymbol* name, - ciSymbol* signature) : ciObject(ciMethodKlass::make()) { - // These fields are always filled in. - _name = name; - _holder = holder; - _signature = new (CURRENT_ENV->arena()) ciSignature(_holder, constantPoolHandle(), signature); - _intrinsic_id = vmIntrinsics::_none; - _liveness = NULL; - _can_be_statically_bound = false; - _method_blocks = NULL; - _method_data = NULL; + ciSymbol* name, + ciSymbol* signature, + ciInstanceKlass* accessor) : + ciObject(ciMethodKlass::make()), + _name( name), + _holder( holder), + _intrinsic_id( vmIntrinsics::_none), + _liveness( NULL), + _can_be_statically_bound(false), + _method_blocks( NULL), + _method_data( NULL) #if defined(COMPILER2) || defined(SHARK) - _flow = NULL; - _bcea = NULL; + , + _flow( NULL), + _bcea( NULL) #endif // COMPILER2 || SHARK +{ + // Usually holder and accessor are the same type but in some cases + // the holder has the wrong class loader (e.g. invokedynamic call + // sites) so we pass the accessor. + _signature = new (CURRENT_ENV->arena()) ciSignature(accessor, constantPoolHandle(), signature); } diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/ci/ciMethod.hpp Sun Oct 16 02:59:24 2011 -0700 @@ -88,7 +88,7 @@ #endif ciMethod(methodHandle h_m); - ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature); + ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor); methodOop get_methodOop() const { methodOop m = (methodOop)get_oop(); diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/ci/ciObjectFactory.cpp --- a/src/share/vm/ci/ciObjectFactory.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/ci/ciObjectFactory.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -374,20 +374,32 @@ // unloaded method. This may need to change. ciMethod* ciObjectFactory::get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature) { - for (int i=0; i<_unloaded_methods->length(); i++) { + ciSymbol* signature, + ciInstanceKlass* accessor) { + ciSignature* that = NULL; + for (int i = 0; i < _unloaded_methods->length(); i++) { ciMethod* entry = _unloaded_methods->at(i); if (entry->holder()->equals(holder) && entry->name()->equals(name) && entry->signature()->as_symbol()->equals(signature)) { - // We've found a match. - return entry; + // Short-circuit slow resolve. + if (entry->signature()->accessing_klass() == accessor) { + // We've found a match. + return entry; + } else { + // Lazily create ciSignature + if (that == NULL) that = new (arena()) ciSignature(accessor, constantPoolHandle(), signature); + if (entry->signature()->equals(that)) { + // We've found a match. + return entry; + } + } } } // This is a new unloaded method. Create it and stick it in // the cache. - ciMethod* new_method = new (arena()) ciMethod(holder, name, signature); + ciMethod* new_method = new (arena()) ciMethod(holder, name, signature, accessor); init_ident_of(new_method); _unloaded_methods->append(new_method); diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/ci/ciObjectFactory.hpp --- a/src/share/vm/ci/ciObjectFactory.hpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/ci/ciObjectFactory.hpp Sun Oct 16 02:59:24 2011 -0700 @@ -108,7 +108,8 @@ // Get the ciMethod representing an unloaded/unfound method. ciMethod* get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature); + ciSymbol* signature, + ciInstanceKlass* accessor); // Get a ciKlass representing an unloaded klass. ciKlass* get_unloaded_klass(ciKlass* accessing_klass, diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/ci/ciSignature.cpp --- a/src/share/vm/ci/ciSignature.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/ci/ciSignature.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -80,7 +80,7 @@ } // ------------------------------------------------------------------ -// ciSignature::return_ciType +// ciSignature::return_type // // What is the return type of this signature? ciType* ciSignature::return_type() const { @@ -88,7 +88,7 @@ } // ------------------------------------------------------------------ -// ciSignature::ciType_at +// ciSignature::type_at // // What is the type of the index'th element of this // signature? @@ -99,6 +99,24 @@ } // ------------------------------------------------------------------ +// ciSignature::equals +// +// Compare this signature to another one. Signatures with different +// accessing classes but with signature-types resolved to the same +// types are defined to be equal. +bool ciSignature::equals(ciSignature* that) { + // Compare signature + if (!this->as_symbol()->equals(that->as_symbol())) return false; + // Compare all types of the arguments + for (int i = 0; i < _count; i++) { + if (this->type_at(i) != that->type_at(i)) return false; + } + // Compare the return type + if (this->return_type() != that->return_type()) return false; + return true; +} + +// ------------------------------------------------------------------ // ciSignature::print_signature void ciSignature::print_signature() { _symbol->print_symbol(); diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/ci/ciSignature.hpp --- a/src/share/vm/ci/ciSignature.hpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/ci/ciSignature.hpp Sun Oct 16 02:59:24 2011 -0700 @@ -43,6 +43,7 @@ int _count; friend class ciMethod; + friend class ciObjectFactory; ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature); @@ -52,6 +53,7 @@ public: ciSymbol* as_symbol() const { return _symbol; } + ciKlass* accessing_klass() const { return _accessing_klass; } ciType* return_type() const; ciType* type_at(int index) const; @@ -59,6 +61,8 @@ int size() const { return _size; } int count() const { return _count; } + bool equals(ciSignature* that); + void print_signature(); void print(); }; diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/opto/runtime.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -997,10 +997,13 @@ force_unwind ? NULL : nm->handler_for_exception_and_pc(exception, pc); if (handler_address == NULL) { + Handle original_exception(thread, exception()); handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true); assert (handler_address != NULL, "must have compiled handler"); - // Update the exception cache only when the unwind was not forced. - if (!force_unwind) { + // Update the exception cache only when the unwind was not forced + // and there didn't happen another exception during the computation of the + // compiled exception handler. + if (!force_unwind && original_exception() == exception()) { nm->add_handler_for_exception_and_pc(exception,pc,handler_address); } } else { diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/prims/methodHandleWalk.cpp --- a/src/share/vm/prims/methodHandleWalk.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/prims/methodHandleWalk.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -1387,10 +1387,8 @@ int total = count1 + count2; if (count1 != -1 && count2 != -1 && total != 0) { // Normalize the collect counts to the invoke_count - tty->print("counts %d %d scaled by %d = ", count2, count1, _invoke_count); if (count1 != 0) _not_taken_count = (int)(_invoke_count * count1 / (double)total); if (count2 != 0) _taken_count = (int)(_invoke_count * count2 / (double)total); - tty->print_cr("%d %d", _taken_count, _not_taken_count); return true; } return false; diff -r bc257a801090 -r 11d17c7d2ee6 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Fri Oct 14 21:45:37 2011 -0700 +++ b/src/share/vm/runtime/sharedRuntime.cpp Sun Oct 16 02:59:24 2011 -0700 @@ -659,12 +659,14 @@ int scope_depth = 0; if (!force_unwind) { int bci = sd->bci(); + bool recursive_exception = false; do { bool skip_scope_increment = false; // exception handler lookup KlassHandle ek (THREAD, exception->klass()); handler_bci = sd->method()->fast_exception_handler_bci_for(ek, bci, THREAD); if (HAS_PENDING_EXCEPTION) { + recursive_exception = true; // We threw an exception while trying to find the exception handler. // Transfer the new exception to the exception handle which will // be set into thread local storage, and do another lookup for an @@ -680,6 +682,9 @@ skip_scope_increment = true; } } + else { + recursive_exception = false; + } if (!top_frame_only && handler_bci < 0 && !skip_scope_increment) { sd = sd->sender(); if (sd != NULL) { @@ -687,7 +692,7 @@ } ++scope_depth; } - } while (!top_frame_only && handler_bci < 0 && sd != NULL); + } while (recursive_exception || (!top_frame_only && handler_bci < 0 && sd != NULL)); } // found handling method => lookup exception handler diff -r bc257a801090 -r 11d17c7d2ee6 test/compiler/6865265/StackOverflowBug.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6865265/StackOverflowBug.java Sun Oct 16 02:59:24 2011 -0700 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 6865265 + * @summary JVM crashes with "missing exception handler" error + * @author volker.simonis@sap.com + * + * @run main/othervm -XX:CompileThreshold=100 -Xbatch -Xss128k StackOverflowBug + */ + + +public class StackOverflowBug { + + public static int run() { + try { + try { + return run(); + } catch (Throwable e) { + // Notice that the class 'Throwable' is NOT resolved by the verifier, + // because the verifier only checks if 'Throwable' is assignable to + // 'java.lang.Throwable' and this check succeeds immediately if the two + // types have equal names (see 'VerificationType::is_assignable_from' which + // is called from 'ClassVerifier::verify_exception_handler_table'). + // This is strange, because if the two classes have different names, + // 'is_assignable_from()' calls 'is_reference_assignable_from()' which resolves + // both classes by calling 'SystemDictionary::resolve_or_fail()'. This call + // also takes into account the current class loader (i.e. the one which was used + // to load this class) and would place a corresponding + // "java.lang.Throwable / current-Classloader" entry into the system dictionary. + // This would in turn allow C2 to see 'java.lang.Throwable' as "loaded" + // (see 'Parse::catch_inline_exceptions()') when this method is compiled. + return 42; + } + } + finally { + } + } + + public static void main(String argv[]) { + run(); + } +} + +/* + public static int run(); + Code: + 0: invokestatic #2 // Method run:()I + 3: istore_0 + 4: iload_0 + 5: ireturn + 6: astore_0 + 7: bipush 42 + 9: istore_1 + 10: iload_1 + 11: ireturn + 12: astore_2 + 13: aload_2 + 14: athrow + Exception table: + from to target type + 0 4 6 Class java/lang/Throwable + 0 4 12 any + 6 10 12 any + 12 13 12 any + + */ diff -r bc257a801090 -r 11d17c7d2ee6 test/compiler/7100757/Test7100757.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7100757/Test7100757.java Sun Oct 16 02:59:24 2011 -0700 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7100757 + * @summary The BitSet.nextSetBit() produces incorrect result in 32bit VM on Sparc + * + * @run main/timeout=300 Test7100757 + */ + +import java.util.*; + +public class Test7100757 { + + public static final int NBITS = 256; + + public static void main(String[] args) { + + BitSet bs = new BitSet(NBITS); + Random rnd = new Random(); + long[] ra = new long[(NBITS+63)/64]; + + for(int l=0; l < 5000000; l++) { + + for(int r = 0; r < ra.length; r++) { + ra[r] = rnd.nextLong(); + } + test(ra, bs); + } + } + + static void test(long[] ra, BitSet bs) { + bs.clear(); + int bits_set = 0; + for(int i = 0, t = 0, b = 0; i < NBITS; i++) { + long bit = 1L << b++; + if((ra[t]&bit) != 0) { + bs.set(i); + bits_set++; + } + if(b == 64) { + t++; + b = 0; + } + } + // Test Long.bitCount() + int check_bits = bs.cardinality(); + if (check_bits != bits_set) { + String bs_str = bs.toString(); + System.err.printf("cardinality bits: %d != %d bs: %s\n", check_bits, bits_set, bs_str); + System.exit(97); + } + // Test Long.numberOfTrailingZeros() + check_bits = 0; + for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { + check_bits++; + } + if (check_bits != bits_set) { + String bs_str = bs.toString(); + System.err.printf("nextSetBit bits: %d != %d bs: %s\n", check_bits, bits_set, bs_str); + System.exit(97); + } + // Test Long.numberOfLeadingZeros() + for(int i = bs.length(); i > 0; i = bs.length()) { + bs.clear(i-1); + } + // Test Long.bitCount() + check_bits = bs.cardinality(); + if (check_bits != 0) { + String bs_str = bs.toString(); + System.err.printf("after clear bits: %d != 0 bs: %s\n", check_bits, bs_str); + System.exit(97); + } + } + +};