mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 12:34:32 +02:00
8149813: Move trusted final field handling from C2 LoadNode::Value to shared code
Reviewed-by: thartmann, kvn
This commit is contained in:
parent
8555d89404
commit
03174f3030
4 changed files with 20 additions and 34 deletions
|
@ -211,6 +211,12 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
|
||||||
// so there is no hacking of finals going on with them.
|
// so there is no hacking of finals going on with them.
|
||||||
if (holder->is_anonymous())
|
if (holder->is_anonymous())
|
||||||
return true;
|
return true;
|
||||||
|
// Trust final fields in all boxed classes
|
||||||
|
if (holder->is_box_klass())
|
||||||
|
return true;
|
||||||
|
// Trust final fields in String
|
||||||
|
if (holder->name() == ciSymbol::java_lang_String())
|
||||||
|
return true;
|
||||||
// Trust Atomic*FieldUpdaters: they are very important for performance, and make up one
|
// Trust Atomic*FieldUpdaters: they are very important for performance, and make up one
|
||||||
// more reason not to use Unsafe, if their final fields are trusted. See more in JDK-8140483.
|
// more reason not to use Unsafe, if their final fields are trusted. See more in JDK-8140483.
|
||||||
if (holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
|
if (holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
|
||||||
|
|
|
@ -1709,38 +1709,10 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
|
||||||
// unsafe field access may not have a constant offset
|
// unsafe field access may not have a constant offset
|
||||||
C->has_unsafe_access(),
|
C->has_unsafe_access(),
|
||||||
"Field accesses must be precise" );
|
"Field accesses must be precise" );
|
||||||
// For oop loads, we expect the _type to be precise
|
// For oop loads, we expect the _type to be precise.
|
||||||
if (klass == env->String_klass() &&
|
|
||||||
adr->is_AddP() && off != Type::OffsetBot) {
|
|
||||||
// For constant Strings treat the final fields as compile time constants.
|
|
||||||
// While we can list what field types java.lang.String has, it is more
|
|
||||||
// future-proof to handle all possible field types, anticipating future
|
|
||||||
// changes and experiments in String code.
|
|
||||||
Node* base = adr->in(AddPNode::Base);
|
|
||||||
const TypeOopPtr* t = phase->type(base)->isa_oopptr();
|
|
||||||
if (t != NULL && t->singleton()) {
|
|
||||||
ciField* field = env->String_klass()->get_field_by_offset(off, false);
|
|
||||||
if (field != NULL && field->is_final()) {
|
|
||||||
ciObject* string = t->const_oop();
|
|
||||||
ciConstant constant = string->as_instance()->field_value(field);
|
|
||||||
// Type::make_from_constant does not handle narrow oops, so handle it here.
|
|
||||||
// Everything else can use the factory method.
|
|
||||||
if ((constant.basic_type() == T_ARRAY || constant.basic_type() == T_OBJECT)
|
|
||||||
&& adr->bottom_type()->is_ptr_to_narrowoop()) {
|
|
||||||
return TypeNarrowOop::make_from_constant(constant.as_object(), true);
|
|
||||||
} else {
|
|
||||||
return Type::make_from_constant(constant, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Optimizations for constant objects
|
// Optimizations for constant objects
|
||||||
ciObject* const_oop = tinst->const_oop();
|
ciObject* const_oop = tinst->const_oop();
|
||||||
if (const_oop != NULL) {
|
if (const_oop != NULL) {
|
||||||
// For constant Boxed value treat the target field as a compile time constant.
|
|
||||||
if (tinst->is_ptr_to_boxed_value()) {
|
|
||||||
return tinst->get_const_boxed_value();
|
|
||||||
} else
|
|
||||||
// For constant CallSites treat the target field as a compile time constant.
|
// For constant CallSites treat the target field as a compile time constant.
|
||||||
if (const_oop->is_call_site()) {
|
if (const_oop->is_call_site()) {
|
||||||
ciCallSite* call_site = const_oop->as_call_site();
|
ciCallSite* call_site = const_oop->as_call_site();
|
||||||
|
|
|
@ -1552,8 +1552,7 @@ Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* dst_array, No
|
||||||
|
|
||||||
if (str->is_Con()) {
|
if (str->is_Con()) {
|
||||||
// Constant source string
|
// Constant source string
|
||||||
const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr();
|
ciTypeArray* src_array_type = get_constant_value(kit, str);
|
||||||
ciTypeArray* src_array_type = t->const_oop()->as_type_array();
|
|
||||||
|
|
||||||
// Check encoding of constant string
|
// Check encoding of constant string
|
||||||
bool src_is_byte = (get_constant_coder(kit, str) == java_lang_String::CODER_LATIN1);
|
bool src_is_byte = (get_constant_coder(kit, str) == java_lang_String::CODER_LATIN1);
|
||||||
|
@ -1673,9 +1672,15 @@ jbyte PhaseStringOpts::get_constant_coder(GraphKit& kit, Node* str) {
|
||||||
|
|
||||||
int PhaseStringOpts::get_constant_length(GraphKit& kit, Node* str) {
|
int PhaseStringOpts::get_constant_length(GraphKit& kit, Node* str) {
|
||||||
assert(str->is_Con(), "String must be constant");
|
assert(str->is_Con(), "String must be constant");
|
||||||
Node* src_array = kit.load_String_value(kit.control(), str);
|
return get_constant_value(kit, str)->length();
|
||||||
const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr();
|
}
|
||||||
return t->const_oop()->as_type_array()->length();
|
|
||||||
|
ciTypeArray* PhaseStringOpts::get_constant_value(GraphKit& kit, Node* str) {
|
||||||
|
assert(str->is_Con(), "String must be constant");
|
||||||
|
const TypeOopPtr* str_type = kit.gvn().type(str)->isa_oopptr();
|
||||||
|
ciInstance* str_instance = str_type->const_oop()->as_instance();
|
||||||
|
ciObject* src_array = str_instance->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object();
|
||||||
|
return src_array->as_type_array();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
|
void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
|
||||||
|
|
|
@ -97,6 +97,9 @@ class PhaseStringOpts : public Phase {
|
||||||
// Returns the length of a constant string
|
// Returns the length of a constant string
|
||||||
int get_constant_length(GraphKit& kit, Node* str);
|
int get_constant_length(GraphKit& kit, Node* str);
|
||||||
|
|
||||||
|
// Returns the value array of a constant string
|
||||||
|
ciTypeArray* get_constant_value(GraphKit& kit, Node* str);
|
||||||
|
|
||||||
// Clean up any leftover nodes
|
// Clean up any leftover nodes
|
||||||
void record_dead_node(Node* node);
|
void record_dead_node(Node* node);
|
||||||
void remove_dead_nodes();
|
void remove_dead_nodes();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue