Merge
This commit is contained in:
commit
fafabe6da0
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -2619,6 +2619,24 @@ int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeV
|
||||
|
||||
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);
|
||||
|
@ -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);)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
89
hotspot/test/compiler/6865265/StackOverflowBug.java
Normal file
89
hotspot/test/compiler/6865265/StackOverflowBug.java
Normal file
@ -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
|
||||
|
||||
*/
|
98
hotspot/test/compiler/7100757/Test7100757.java
Normal file
98
hotspot/test/compiler/7100757/Test7100757.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user