mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
6958668: repeated uncommon trapping for new of klass which is being initialized
Reviewed-by: kvn, jrose
This commit is contained in:
parent
7533d0caf7
commit
d3c3800a29
5 changed files with 69 additions and 35 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -44,9 +44,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
|
|||
_flags = ciFlags(access_flags);
|
||||
_has_finalizer = access_flags.has_finalizer();
|
||||
_has_subklass = ik->subklass() != NULL;
|
||||
_is_initialized = ik->is_initialized();
|
||||
// Next line must follow and use the result of the previous line:
|
||||
_is_linked = _is_initialized || ik->is_linked();
|
||||
_init_state = (instanceKlass::ClassState)ik->get_init_state();
|
||||
_nonstatic_field_size = ik->nonstatic_field_size();
|
||||
_has_nonstatic_fields = ik->has_nonstatic_fields();
|
||||
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
|
||||
|
@ -91,8 +89,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
|
|||
: ciKlass(name, ciInstanceKlassKlass::make())
|
||||
{
|
||||
assert(name->byte_at(0) != '[', "not an instance klass");
|
||||
_is_initialized = false;
|
||||
_is_linked = false;
|
||||
_init_state = (instanceKlass::ClassState)0;
|
||||
_nonstatic_field_size = -1;
|
||||
_has_nonstatic_fields = false;
|
||||
_nonstatic_fields = NULL;
|
||||
|
@ -109,21 +106,10 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
|
|||
|
||||
// ------------------------------------------------------------------
|
||||
// ciInstanceKlass::compute_shared_is_initialized
|
||||
bool ciInstanceKlass::compute_shared_is_initialized() {
|
||||
void ciInstanceKlass::compute_shared_init_state() {
|
||||
GUARDED_VM_ENTRY(
|
||||
instanceKlass* ik = get_instanceKlass();
|
||||
_is_initialized = ik->is_initialized();
|
||||
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;
|
||||
_init_state = (instanceKlass::ClassState)ik->get_init_state();
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -39,9 +39,8 @@ private:
|
|||
jobject _loader;
|
||||
jobject _protection_domain;
|
||||
|
||||
instanceKlass::ClassState _init_state; // state of class
|
||||
bool _is_shared;
|
||||
bool _is_initialized;
|
||||
bool _is_linked;
|
||||
bool _has_finalizer;
|
||||
bool _has_subklass;
|
||||
bool _has_nonstatic_fields;
|
||||
|
@ -87,27 +86,34 @@ protected:
|
|||
|
||||
bool is_shared() { return _is_shared; }
|
||||
|
||||
bool compute_shared_is_initialized();
|
||||
bool compute_shared_is_linked();
|
||||
void compute_shared_init_state();
|
||||
bool compute_shared_has_subklass();
|
||||
int compute_shared_nof_implementors();
|
||||
int compute_nonstatic_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:
|
||||
// Has this klass been initialized?
|
||||
bool is_initialized() {
|
||||
if (_is_shared && !_is_initialized) {
|
||||
return is_loaded() && compute_shared_is_initialized();
|
||||
update_if_shared(instanceKlass::fully_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?
|
||||
bool is_linked() {
|
||||
if (_is_shared && !_is_linked) {
|
||||
return is_loaded() && compute_shared_is_linked();
|
||||
}
|
||||
return _is_linked;
|
||||
update_if_shared(instanceKlass::linked);
|
||||
return _init_state >= instanceKlass::linked;
|
||||
}
|
||||
|
||||
// General klass information.
|
||||
|
|
|
@ -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
|
||||
// v-calls. Let interface calls happen.
|
||||
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()) {
|
||||
uncommon_trap(Deoptimization::Reason_uninitialized,
|
||||
Deoptimization::Action_reinterpret,
|
||||
|
|
|
@ -480,6 +480,7 @@ class Parse : public GraphKit {
|
|||
bool push_constant(ciConstant con, bool require_constant = false);
|
||||
|
||||
// implementation of object creation bytecodes
|
||||
void emit_guard_for_new(ciInstanceKlass* klass);
|
||||
void do_new();
|
||||
void do_newarray(BasicType elemtype);
|
||||
void do_anewarray();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -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-----------------------------------------
|
||||
void Parse::do_new() {
|
||||
kill_dead_locals();
|
||||
|
@ -206,7 +243,7 @@ void Parse::do_new() {
|
|||
assert(will_link, "_new: typeflow responsibility");
|
||||
|
||||
// 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->name() == ciSymbol::java_lang_Class() ||
|
||||
iter().is_unresolved_klass()) {
|
||||
|
@ -215,6 +252,9 @@ void Parse::do_new() {
|
|||
klass);
|
||||
return;
|
||||
}
|
||||
if (klass->is_being_initialized()) {
|
||||
emit_guard_for_new(klass);
|
||||
}
|
||||
|
||||
Node* kls = makecon(TypeKlassPtr::make(klass));
|
||||
Node* obj = new_instance(kls);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue