diff --git a/src/cpu/sparc/vm/sparc.ad b/src/cpu/sparc/vm/sparc.ad index d7bf2d85fe8e2476408710dff3fc099d171de31f..1484f6b9792f4afa9d206c47fe62f3839263479b 100644 --- a/src/cpu/sparc/vm/sparc.ad +++ b/src/cpu/sparc/vm/sparc.ad @@ -10476,7 +10476,7 @@ instruct countTrailingZerosI(iRegI dst, iRegI src, flagsReg cr) %{ 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 --git a/src/cpu/x86/vm/frame_x86.cpp b/src/cpu/x86/vm/frame_x86.cpp index 3d82d062289ae69c3126122cf70b1caa515ad973..511e344ba6ced482274627b4529e67c962f6f565 100644 --- a/src/cpu/x86/vm/frame_x86.cpp +++ b/src/cpu/x86/vm/frame_x86.cpp @@ -232,11 +232,13 @@ bool frame::safe_for_sender(JavaThread *thread) { 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 @@ intptr_t *frame::initial_deoptimization_info() { // used to reset the saved FP return fp(); } - diff --git a/src/cpu/x86/vm/methodHandles_x86.cpp b/src/cpu/x86/vm/methodHandles_x86.cpp index dd741fda0d85d4b9e024dce42b59df7038bbf34a..b998fa50d87d431347020b664ce09b30dad71de0 100644 --- a/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/src/cpu/x86/vm/methodHandles_x86.cpp @@ -410,8 +410,8 @@ void MethodHandles::RicochetFrame::verify_offsets() { 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 --git a/src/cpu/x86/vm/methodHandles_x86.hpp b/src/cpu/x86/vm/methodHandles_x86.hpp index bf85c33c731165a752e966e07acbea76f553b5ee..bc8fc3690191825d055aa38ac3a35696b99dcfb3 100644 --- a/src/cpu/x86/vm/methodHandles_x86.hpp +++ b/src/cpu/x86/vm/methodHandles_x86.hpp @@ -132,7 +132,10 @@ class RicochetFrame { 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 --git a/src/share/vm/c1/c1_GraphBuilder.cpp b/src/share/vm/c1/c1_GraphBuilder.cpp index e103fbf44e2750c7e3eb0d7a16649808d6ab1239..0c3f32bcdab4cdc078a18bbe2638dc3c9d8d54ea 100644 --- a/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1165,11 +1165,11 @@ void GraphBuilder::_goto(int from_bci, int to_bci) { 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 @@ void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* sta 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 --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp index c2c2f7c7fa81593971249fea99e168c6970dd40a..f9099e940f7b3cf8aa922e8837413ea29b7e3a72 100644 --- a/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2493,7 +2493,7 @@ void LIRGenerator::do_Goto(Goto* x) { // 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 --git a/src/share/vm/c1/c1_LinearScan.cpp b/src/share/vm/c1/c1_LinearScan.cpp index 38ee82acdd9499ba9b4426151ec317ae28167c42..ebb06837284e775a81c85c9fa3e4d24448b2acbe 100644 --- a/src/share/vm/c1/c1_LinearScan.cpp +++ b/src/share/vm/c1/c1_LinearScan.cpp @@ -2619,6 +2619,24 @@ int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArrayfpu_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 --git a/src/share/vm/ci/ciEnv.cpp b/src/share/vm/ci/ciEnv.cpp index 82492a08e946ccb9db71adf447327374711f4067..1366177238cf729697efd96e412d3c5da2037ded 100644 --- a/src/share/vm/ci/ciEnv.cpp +++ b/src/share/vm/ci/ciEnv.cpp @@ -473,6 +473,7 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, } 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 @@ ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool, 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 @@ ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool, // 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 @@ ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, // 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 @@ ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool, 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 --git a/src/share/vm/ci/ciEnv.hpp b/src/share/vm/ci/ciEnv.hpp index f5242ca024db481ca8c26376a1fb7da2f80f5757..12f4bb2267fca6e1cb5bd25370dd358d286cafa2 100644 --- a/src/share/vm/ci/ciEnv.hpp +++ b/src/share/vm/ci/ciEnv.hpp @@ -153,7 +153,8 @@ private: 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 @@ private: // 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 @@ private: // 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 --git a/src/share/vm/ci/ciMethod.cpp b/src/share/vm/ci/ciMethod.cpp index a985d5e28df7d1bc6509c96916d9eedf4b6acd7d..6049d7b93301abcc2b9d8eb544bba374c0a18086 100644 --- a/src/share/vm/ci/ciMethod.cpp +++ b/src/share/vm/ci/ciMethod.cpp @@ -148,21 +148,27 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) { // // 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 --git a/src/share/vm/ci/ciMethod.hpp b/src/share/vm/ci/ciMethod.hpp index db7175284066cd560f8b5d63ddea209141453036..45a491f9d22a001889cd045eb56ba6e1f662c02f 100644 --- a/src/share/vm/ci/ciMethod.hpp +++ b/src/share/vm/ci/ciMethod.hpp @@ -88,7 +88,7 @@ class ciMethod : public ciObject { #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 --git a/src/share/vm/ci/ciObjectFactory.cpp b/src/share/vm/ci/ciObjectFactory.cpp index b0e9064a09d6e4567fc9a6581b350deddc78d93a..9aa6b261118334c8f211c34eb670d11906c34dc4 100644 --- a/src/share/vm/ci/ciObjectFactory.cpp +++ b/src/share/vm/ci/ciObjectFactory.cpp @@ -374,20 +374,32 @@ ciObject* ciObjectFactory::create_new_object(oop o) { // 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 --git a/src/share/vm/ci/ciObjectFactory.hpp b/src/share/vm/ci/ciObjectFactory.hpp index 6222b9f85bc59f1437cdd997159c0319be9fea48..26cc2c30c345705811513861779a36a46322f2c5 100644 --- a/src/share/vm/ci/ciObjectFactory.hpp +++ b/src/share/vm/ci/ciObjectFactory.hpp @@ -108,7 +108,8 @@ public: // 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 --git a/src/share/vm/ci/ciSignature.cpp b/src/share/vm/ci/ciSignature.cpp index 8754fb4e8937dc85eebb246a86dc4296e68a8077..229a904e9b814a1b4664c40c611498d7611d8a60 100644 --- a/src/share/vm/ci/ciSignature.cpp +++ b/src/share/vm/ci/ciSignature.cpp @@ -80,7 +80,7 @@ ciSignature::ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciS } // ------------------------------------------------------------------ -// ciSignature::return_ciType +// ciSignature::return_type // // What is the return type of this signature? ciType* ciSignature::return_type() const { @@ -88,7 +88,7 @@ ciType* ciSignature::return_type() const { } // ------------------------------------------------------------------ -// ciSignature::ciType_at +// ciSignature::type_at // // What is the type of the index'th element of this // signature? @@ -98,6 +98,24 @@ ciType* ciSignature::type_at(int index) const { return _types->at(index); } +// ------------------------------------------------------------------ +// 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() { diff --git a/src/share/vm/ci/ciSignature.hpp b/src/share/vm/ci/ciSignature.hpp index aaeac416c817807a690cb2f40e3be43230e35ba8..25ba097ccaf90c78933c709d3c66712681b4859e 100644 --- a/src/share/vm/ci/ciSignature.hpp +++ b/src/share/vm/ci/ciSignature.hpp @@ -43,6 +43,7 @@ private: int _count; friend class ciMethod; + friend class ciObjectFactory; ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature); @@ -52,6 +53,7 @@ private: 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 @@ public: int size() const { return _size; } int count() const { return _count; } + bool equals(ciSignature* that); + void print_signature(); void print(); }; diff --git a/src/share/vm/opto/runtime.cpp b/src/share/vm/opto/runtime.cpp index a4495ea7474f676a3966a963539a7f6476b4796d..0c2f84c85b94723f9c282f999dd75e3b070f6205 100644 --- a/src/share/vm/opto/runtime.cpp +++ b/src/share/vm/opto/runtime.cpp @@ -997,10 +997,13 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t 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 --git a/src/share/vm/prims/methodHandleWalk.cpp b/src/share/vm/prims/methodHandleWalk.cpp index 3f313074b8fe3de20b68c0dfb8848d7e14a339f4..d4d9a7130a5cc4473384ba3c397247ea45daf8f1 100644 --- a/src/share/vm/prims/methodHandleWalk.cpp +++ b/src/share/vm/prims/methodHandleWalk.cpp @@ -1387,10 +1387,8 @@ bool MethodHandleCompiler::fetch_counts(ArgToken arg1, ArgToken arg2) { 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 --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp index 34369e82d70b0335d42071084e902c023f7635ee..6f4ff3388ec3ea509ddba1cb3e1fe5f157d4b920 100644 --- a/src/share/vm/runtime/sharedRuntime.cpp +++ b/src/share/vm/runtime/sharedRuntime.cpp @@ -659,12 +659,14 @@ address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, 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 @@ address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, 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 @@ address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, } ++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 --git a/test/compiler/6865265/StackOverflowBug.java b/test/compiler/6865265/StackOverflowBug.java new file mode 100644 index 0000000000000000000000000000000000000000..51303041eee410a52b4e7fdb53881c7ea5a35280 --- /dev/null +++ b/test/compiler/6865265/StackOverflowBug.java @@ -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 --git a/test/compiler/7100757/Test7100757.java b/test/compiler/7100757/Test7100757.java new file mode 100644 index 0000000000000000000000000000000000000000..daa0bfeb22eb9544ae5929a71a26c64faaa309c1 --- /dev/null +++ b/test/compiler/7100757/Test7100757.java @@ -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); + } + } + +};