提交 2939dd56 编写于 作者: N never

6958668: repeated uncommon trapping for new of klass which is being initialized

Reviewed-by: kvn, jrose
上级 7dfc0570
/* /*
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -44,9 +44,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : ...@@ -44,9 +44,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
_flags = ciFlags(access_flags); _flags = ciFlags(access_flags);
_has_finalizer = access_flags.has_finalizer(); _has_finalizer = access_flags.has_finalizer();
_has_subklass = ik->subklass() != NULL; _has_subklass = ik->subklass() != NULL;
_is_initialized = ik->is_initialized(); _init_state = (instanceKlass::ClassState)ik->get_init_state();
// Next line must follow and use the result of the previous line:
_is_linked = _is_initialized || ik->is_linked();
_nonstatic_field_size = ik->nonstatic_field_size(); _nonstatic_field_size = ik->nonstatic_field_size();
_has_nonstatic_fields = ik->has_nonstatic_fields(); _has_nonstatic_fields = ik->has_nonstatic_fields();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
...@@ -91,8 +89,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name, ...@@ -91,8 +89,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
: ciKlass(name, ciInstanceKlassKlass::make()) : ciKlass(name, ciInstanceKlassKlass::make())
{ {
assert(name->byte_at(0) != '[', "not an instance klass"); assert(name->byte_at(0) != '[', "not an instance klass");
_is_initialized = false; _init_state = (instanceKlass::ClassState)0;
_is_linked = false;
_nonstatic_field_size = -1; _nonstatic_field_size = -1;
_has_nonstatic_fields = false; _has_nonstatic_fields = false;
_nonstatic_fields = NULL; _nonstatic_fields = NULL;
...@@ -109,21 +106,10 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name, ...@@ -109,21 +106,10 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciInstanceKlass::compute_shared_is_initialized // ciInstanceKlass::compute_shared_is_initialized
bool ciInstanceKlass::compute_shared_is_initialized() { void ciInstanceKlass::compute_shared_init_state() {
GUARDED_VM_ENTRY( GUARDED_VM_ENTRY(
instanceKlass* ik = get_instanceKlass(); instanceKlass* ik = get_instanceKlass();
_is_initialized = ik->is_initialized(); _init_state = (instanceKlass::ClassState)ik->get_init_state();
return _is_initialized;
)
}
// ------------------------------------------------------------------
// ciInstanceKlass::compute_shared_is_linked
bool ciInstanceKlass::compute_shared_is_linked() {
GUARDED_VM_ENTRY(
instanceKlass* ik = get_instanceKlass();
_is_linked = ik->is_linked();
return _is_linked;
) )
} }
......
/* /*
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,9 +39,8 @@ private: ...@@ -39,9 +39,8 @@ private:
jobject _loader; jobject _loader;
jobject _protection_domain; jobject _protection_domain;
instanceKlass::ClassState _init_state; // state of class
bool _is_shared; bool _is_shared;
bool _is_initialized;
bool _is_linked;
bool _has_finalizer; bool _has_finalizer;
bool _has_subklass; bool _has_subklass;
bool _has_nonstatic_fields; bool _has_nonstatic_fields;
...@@ -87,27 +86,34 @@ protected: ...@@ -87,27 +86,34 @@ protected:
bool is_shared() { return _is_shared; } bool is_shared() { return _is_shared; }
bool compute_shared_is_initialized(); void compute_shared_init_state();
bool compute_shared_is_linked();
bool compute_shared_has_subklass(); bool compute_shared_has_subklass();
int compute_shared_nof_implementors(); int compute_shared_nof_implementors();
int compute_nonstatic_fields(); int compute_nonstatic_fields();
GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields); GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields);
// Update the init_state for shared klasses
void update_if_shared(instanceKlass::ClassState expected) {
if (_is_shared && _init_state != expected) {
if (is_loaded()) compute_shared_init_state();
}
}
public: public:
// Has this klass been initialized? // Has this klass been initialized?
bool is_initialized() { bool is_initialized() {
if (_is_shared && !_is_initialized) { update_if_shared(instanceKlass::fully_initialized);
return is_loaded() && compute_shared_is_initialized(); return _init_state == instanceKlass::fully_initialized;
} }
return _is_initialized; // Is this klass being initialized?
bool is_being_initialized() {
update_if_shared(instanceKlass::being_initialized);
return _init_state == instanceKlass::being_initialized;
} }
// Has this klass been linked? // Has this klass been linked?
bool is_linked() { bool is_linked() {
if (_is_shared && !_is_linked) { update_if_shared(instanceKlass::linked);
return is_loaded() && compute_shared_is_linked(); return _init_state >= instanceKlass::linked;
}
return _is_linked;
} }
// General klass information. // General klass information.
......
...@@ -343,7 +343,8 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl ...@@ -343,7 +343,8 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl
// being initialized. Uncommon-trap for not-initialized static or // being initialized. Uncommon-trap for not-initialized static or
// v-calls. Let interface calls happen. // v-calls. Let interface calls happen.
ciInstanceKlass* holder_klass = dest_method->holder(); ciInstanceKlass* holder_klass = dest_method->holder();
if (!holder_klass->is_initialized() && if (!holder_klass->is_being_initialized() &&
!holder_klass->is_initialized() &&
!holder_klass->is_interface()) { !holder_klass->is_interface()) {
uncommon_trap(Deoptimization::Reason_uninitialized, uncommon_trap(Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret, Deoptimization::Action_reinterpret,
......
...@@ -480,6 +480,7 @@ class Parse : public GraphKit { ...@@ -480,6 +480,7 @@ class Parse : public GraphKit {
bool push_constant(ciConstant con, bool require_constant = false); bool push_constant(ciConstant con, bool require_constant = false);
// implementation of object creation bytecodes // implementation of object creation bytecodes
void emit_guard_for_new(ciInstanceKlass* klass);
void do_new(); void do_new();
void do_newarray(BasicType elemtype); void do_newarray(BasicType elemtype);
void do_anewarray(); void do_anewarray();
......
/* /*
* Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -197,6 +197,43 @@ void Parse::array_store_check() { ...@@ -197,6 +197,43 @@ void Parse::array_store_check() {
} }
void Parse::emit_guard_for_new(ciInstanceKlass* klass) {
// Emit guarded new
// if (klass->_init_thread != current_thread ||
// klass->_init_state != being_initialized)
// uncommon_trap
Node* cur_thread = _gvn.transform( new (C, 1) ThreadLocalNode() );
Node* merge = new (C, 3) RegionNode(3);
_gvn.set_type(merge, Type::CONTROL);
Node* kls = makecon(TypeKlassPtr::make(klass));
Node* init_thread_offset = _gvn.MakeConX(instanceKlass::init_thread_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset);
Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS);
Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq);
IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
set_control(IfTrue(iff));
merge->set_req(1, IfFalse(iff));
Node* init_state_offset = _gvn.MakeConX(instanceKlass::init_state_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
adr_node = basic_plus_adr(kls, kls, init_state_offset);
Node* init_state = make_load(NULL, adr_node, TypeInt::INT, T_INT);
Node* being_init = _gvn.intcon(instanceKlass::being_initialized);
tst = Bool( CmpI( init_state, being_init), BoolTest::eq);
iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
set_control(IfTrue(iff));
merge->set_req(2, IfFalse(iff));
PreserveJVMState pjvms(this);
record_for_igvn(merge);
set_control(merge);
uncommon_trap(Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret,
klass);
}
//------------------------------do_new----------------------------------------- //------------------------------do_new-----------------------------------------
void Parse::do_new() { void Parse::do_new() {
kill_dead_locals(); kill_dead_locals();
...@@ -206,7 +243,7 @@ void Parse::do_new() { ...@@ -206,7 +243,7 @@ void Parse::do_new() {
assert(will_link, "_new: typeflow responsibility"); assert(will_link, "_new: typeflow responsibility");
// Should initialize, or throw an InstantiationError? // Should initialize, or throw an InstantiationError?
if (!klass->is_initialized() || if (!klass->is_initialized() && !klass->is_being_initialized() ||
klass->is_abstract() || klass->is_interface() || klass->is_abstract() || klass->is_interface() ||
klass->name() == ciSymbol::java_lang_Class() || klass->name() == ciSymbol::java_lang_Class() ||
iter().is_unresolved_klass()) { iter().is_unresolved_klass()) {
...@@ -215,6 +252,9 @@ void Parse::do_new() { ...@@ -215,6 +252,9 @@ void Parse::do_new() {
klass); klass);
return; return;
} }
if (klass->is_being_initialized()) {
emit_guard_for_new(klass);
}
Node* kls = makecon(TypeKlassPtr::make(klass)); Node* kls = makecon(TypeKlassPtr::make(klass));
Node* obj = new_instance(kls); Node* obj = new_instance(kls);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册