提交 92f8f750 编写于 作者: A anoll

Merge

...@@ -418,7 +418,7 @@ void CompiledIC::compute_monomorphic_entry(methodHandle method, ...@@ -418,7 +418,7 @@ void CompiledIC::compute_monomorphic_entry(methodHandle method,
TRAPS) { TRAPS) {
nmethod* method_code = method->code(); nmethod* method_code = method->code();
address entry = NULL; address entry = NULL;
if (method_code != NULL) { if (method_code != NULL && method_code->is_in_use()) {
// Call to compiled code // Call to compiled code
if (static_bound || is_optimized) { if (static_bound || is_optimized) {
entry = method_code->verified_entry_point(); entry = method_code->verified_entry_point();
...@@ -545,7 +545,7 @@ void CompiledStaticCall::set(const StaticCallInfo& info) { ...@@ -545,7 +545,7 @@ void CompiledStaticCall::set(const StaticCallInfo& info) {
void CompiledStaticCall::compute_entry(methodHandle m, StaticCallInfo& info) { void CompiledStaticCall::compute_entry(methodHandle m, StaticCallInfo& info) {
nmethod* m_code = m->code(); nmethod* m_code = m->code();
info._callee = m; info._callee = m;
if (m_code != NULL) { if (m_code != NULL && m_code->is_in_use()) {
info._to_interpreter = false; info._to_interpreter = false;
info._entry = m_code->verified_entry_point(); info._entry = m_code->verified_entry_point();
} else { } else {
......
...@@ -459,7 +459,7 @@ const char* nmethod::compile_kind() const { ...@@ -459,7 +459,7 @@ const char* nmethod::compile_kind() const {
// Fill in default values for various flag fields // Fill in default values for various flag fields
void nmethod::init_defaults() { void nmethod::init_defaults() {
_state = alive; _state = in_use;
_marked_for_reclamation = 0; _marked_for_reclamation = 0;
_has_flushed_dependencies = 0; _has_flushed_dependencies = 0;
_has_unsafe_access = 0; _has_unsafe_access = 0;
...@@ -1660,8 +1660,8 @@ void nmethod::do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred) ...@@ -1660,8 +1660,8 @@ void nmethod::do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred)
CompiledICHolder* cichk_oop = ic->cached_icholder(); CompiledICHolder* cichk_oop = ic->cached_icholder();
if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) && if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) &&
cichk_oop->holder_klass()->is_loader_alive(is_alive)) { cichk_oop->holder_klass()->is_loader_alive(is_alive)) {
continue; continue;
} }
} else { } else {
Metadata* ic_oop = ic->cached_metadata(); Metadata* ic_oop = ic->cached_metadata();
if (ic_oop != NULL) { if (ic_oop != NULL) {
...@@ -1677,8 +1677,8 @@ void nmethod::do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred) ...@@ -1677,8 +1677,8 @@ void nmethod::do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred)
ShouldNotReachHere(); ShouldNotReachHere();
} }
} }
} }
ic->set_to_clean(); ic->set_to_clean();
} }
} }
} }
...@@ -2393,8 +2393,8 @@ void nmethod::verify() { ...@@ -2393,8 +2393,8 @@ void nmethod::verify() {
void nmethod::verify_interrupt_point(address call_site) { void nmethod::verify_interrupt_point(address call_site) {
// Verify IC only when nmethod installation is finished. // Verify IC only when nmethod installation is finished.
bool is_installed = (method()->code() == this) // nmethod is in state 'alive' and installed bool is_installed = (method()->code() == this) // nmethod is in state 'in_use' and installed
|| !this->is_in_use(); // nmethod is installed, but not in 'alive' state || !this->is_in_use(); // nmethod is installed, but not in 'in_use' state
if (is_installed) { if (is_installed) {
Thread *cur = Thread::current(); Thread *cur = Thread::current();
if (CompiledIC_lock->owner() == cur || if (CompiledIC_lock->owner() == cur ||
......
...@@ -184,11 +184,12 @@ class nmethod : public CodeBlob { ...@@ -184,11 +184,12 @@ class nmethod : public CodeBlob {
bool _oops_are_stale; // indicates that it's no longer safe to access oops section bool _oops_are_stale; // indicates that it's no longer safe to access oops section
#endif #endif
enum { alive = 0, enum { in_use = 0, // executable nmethod
not_entrant = 1, // uncommon trap has happened but activations may still exist not_entrant = 1, // marked for deoptimization but activations may still exist,
zombie = 2, // will be transformed to zombie when all activations are gone
unloaded = 3 }; zombie = 2, // no activations exist, nmethod is ready for purge
unloaded = 3 }; // there should be no activations, should not be called,
// will be transformed to zombie immediately
jbyte _scavenge_root_state; jbyte _scavenge_root_state;
...@@ -407,8 +408,8 @@ class nmethod : public CodeBlob { ...@@ -407,8 +408,8 @@ class nmethod : public CodeBlob {
address verified_entry_point() const { return _verified_entry_point; } // if klass is correct address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
// flag accessing and manipulation // flag accessing and manipulation
bool is_in_use() const { return _state == alive; } bool is_in_use() const { return _state == in_use; }
bool is_alive() const { return _state == alive || _state == not_entrant; } bool is_alive() const { return _state == in_use || _state == not_entrant; }
bool is_not_entrant() const { return _state == not_entrant; } bool is_not_entrant() const { return _state == not_entrant; }
bool is_zombie() const { return _state == zombie; } bool is_zombie() const { return _state == zombie; }
bool is_unloaded() const { return _state == unloaded; } bool is_unloaded() const { return _state == unloaded; }
......
...@@ -2071,6 +2071,11 @@ const Type *LoadNode::klass_value_common( PhaseTransform *phase ) const { ...@@ -2071,6 +2071,11 @@ const Type *LoadNode::klass_value_common( PhaseTransform *phase ) const {
if (t != NULL) { if (t != NULL) {
// constant oop => constant klass // constant oop => constant klass
if (offset == java_lang_Class::array_klass_offset_in_bytes()) { if (offset == java_lang_Class::array_klass_offset_in_bytes()) {
if (t->is_void()) {
// We cannot create a void array. Since void is a primitive type return null
// klass. Users of this result need to do a null check on the returned klass.
return TypePtr::NULL_PTR;
}
return TypeKlassPtr::make(ciArrayKlass::make(t)); return TypeKlassPtr::make(ciArrayKlass::make(t));
} }
if (!t->is_klass()) { if (!t->is_klass()) {
......
...@@ -1178,12 +1178,12 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, ...@@ -1178,12 +1178,12 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread,
CodeBlob* caller_cb = caller_frame.cb(); CodeBlob* caller_cb = caller_frame.cb();
guarantee(caller_cb != NULL && caller_cb->is_nmethod(), "must be called from nmethod"); guarantee(caller_cb != NULL && caller_cb->is_nmethod(), "must be called from nmethod");
nmethod* caller_nm = caller_cb->as_nmethod_or_null(); nmethod* caller_nm = caller_cb->as_nmethod_or_null();
// make sure caller is not getting deoptimized // make sure caller is not getting deoptimized
// and removed before we are done with it. // and removed before we are done with it.
// CLEANUP - with lazy deopt shouldn't need this lock // CLEANUP - with lazy deopt shouldn't need this lock
nmethodLocker caller_lock(caller_nm); nmethodLocker caller_lock(caller_nm);
// determine call info & receiver // determine call info & receiver
// note: a) receiver is NULL for static calls // note: a) receiver is NULL for static calls
// b) an exception is thrown if receiver is NULL for non-static calls // b) an exception is thrown if receiver is NULL for non-static calls
...@@ -1198,6 +1198,11 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, ...@@ -1198,6 +1198,11 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread,
(!is_virtual && invoke_code == Bytecodes::_invokedynamic) || (!is_virtual && invoke_code == Bytecodes::_invokedynamic) ||
( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode"); ( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode");
// We do not patch the call site if the caller nmethod has been made non-entrant.
if (!caller_nm->is_in_use()) {
return callee_method;
}
#ifndef PRODUCT #ifndef PRODUCT
// tracing/debugging/statistics // tracing/debugging/statistics
int *addr = (is_optimized) ? (&_resolve_opt_virtual_ctr) : int *addr = (is_optimized) ? (&_resolve_opt_virtual_ctr) :
...@@ -1237,6 +1242,10 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, ...@@ -1237,6 +1242,10 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread,
// Make sure the callee nmethod does not get deoptimized and removed before // Make sure the callee nmethod does not get deoptimized and removed before
// we are done patching the code. // we are done patching the code.
nmethod* callee_nm = callee_method->code(); nmethod* callee_nm = callee_method->code();
if (callee_nm != NULL && !callee_nm->is_in_use()) {
// Patch call site to C2I adapter if callee nmethod is deoptimized or unloaded.
callee_nm = NULL;
}
nmethodLocker nl_callee(callee_nm); nmethodLocker nl_callee(callee_nm);
#ifdef ASSERT #ifdef ASSERT
address dest_entry_point = callee_nm == NULL ? 0 : callee_nm->entry_point(); // used below address dest_entry_point = callee_nm == NULL ? 0 : callee_nm->entry_point(); // used below
...@@ -1258,15 +1267,24 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, ...@@ -1258,15 +1267,24 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread,
{ {
MutexLocker ml_patch(CompiledIC_lock); MutexLocker ml_patch(CompiledIC_lock);
// Lock blocks for safepoint during which both nmethods can change state.
// Now that we are ready to patch if the Method* was redefined then // Now that we are ready to patch if the Method* was redefined then
// don't update call site and let the caller retry. // don't update call site and let the caller retry.
// Don't update call site if caller nmethod has been made non-entrant
if (!callee_method->is_old()) { // as it is a waste of time.
// Don't update call site if callee nmethod was unloaded or deoptimized.
// Don't update call site if callee nmethod was replaced by an other nmethod
// which may happen when multiply alive nmethod (tiered compilation)
// will be supported.
if (!callee_method->is_old() && caller_nm->is_in_use() &&
(callee_nm == NULL || callee_nm->is_in_use() && (callee_method->code() == callee_nm))) {
#ifdef ASSERT #ifdef ASSERT
// We must not try to patch to jump to an already unloaded method. // We must not try to patch to jump to an already unloaded method.
if (dest_entry_point != 0) { if (dest_entry_point != 0) {
assert(CodeCache::find_blob(dest_entry_point) != NULL, CodeBlob* cb = CodeCache::find_blob(dest_entry_point);
"should not unload nmethod while locked"); assert((cb != NULL) && cb->is_nmethod() && (((nmethod*)cb) == callee_nm),
"should not call unloaded nmethod");
} }
#endif #endif
if (is_virtual) { if (is_virtual) {
......
...@@ -46,13 +46,17 @@ public class SpreadNullArg { ...@@ -46,13 +46,17 @@ public class SpreadNullArg {
mh_spread_target = mh_spread_target =
MethodHandles.lookup().findStatic(SpreadNullArg.class, "target_spread_arg", mt_ref_arg); MethodHandles.lookup().findStatic(SpreadNullArg.class, "target_spread_arg", mt_ref_arg);
result = (int) mh_spreadInvoker.invokeExact(mh_spread_target, (Object[]) null); result = (int) mh_spreadInvoker.invokeExact(mh_spread_target, (Object[]) null);
} catch(NullPointerException e) { throw new Error("Expected IllegalArgumentException was not thrown");
// Expected exception - do nothing! } catch (IllegalArgumentException e) {
} catch(Throwable e) { System.out.println("Expected exception : " + e);
} catch (Throwable e) {
throw new Error(e); throw new Error(e);
} }
if (result != 42) throw new Error("Expected NullPointerException was not thrown"); if (result != 42) {
throw new Error("result [" + result
+ "] != 42 : Expected IllegalArgumentException was not thrown?");
}
} }
public static int target_spread_arg(Integer i1) { public static int target_spread_arg(Integer i1) {
......
/*
* Copyright (c) 2013, 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 8029366
* @summary ShouldNotReachHere error when creating an array with component type of void
*/
public class ArrayNewInstanceOfVoid {
public static void main(String[] args) {
for (int i = 0; i < 100_000; i++) {
test();
}
}
private static void test() {
try {
java.lang.reflect.Array.newInstance(void.class, 2);
} catch (IllegalArgumentException e) {
// expected
}
}
}
...@@ -34,8 +34,9 @@ ...@@ -34,8 +34,9 @@
*/ */
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
class C1ObjectSpillInLogicOp {
static public void main(String[] args) { public class C1ObjectSpillInLogicOp {
public static void main(String[] args) {
AtomicReferenceArray<Integer> x = new AtomicReferenceArray(128); AtomicReferenceArray<Integer> x = new AtomicReferenceArray(128);
Integer y = new Integer(0); Integer y = new Integer(0);
for (int i = 0; i < 50000; i++) { for (int i = 0; i < 50000; i++) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册