8149813: Move trusted final field handling from C2 LoadNode::Value to shared code

Reviewed-by: thartmann, kvn
This commit is contained in:
Aleksey Shipilev 2016-02-15 23:45:15 +03:00
parent 8555d89404
commit 03174f3030
4 changed files with 20 additions and 34 deletions

View file

@ -211,6 +211,12 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
// so there is no hacking of finals going on with them.
if (holder->is_anonymous())
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
// 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() ||

View file

@ -1709,38 +1709,10 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
// unsafe field access may not have a constant offset
C->has_unsafe_access(),
"Field accesses must 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);
}
}
}
}
// For oop loads, we expect the _type to be precise.
// Optimizations for constant objects
ciObject* const_oop = tinst->const_oop();
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.
if (const_oop->is_call_site()) {
ciCallSite* call_site = const_oop->as_call_site();

View file

@ -1552,8 +1552,7 @@ Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* dst_array, No
if (str->is_Con()) {
// Constant source string
const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr();
ciTypeArray* src_array_type = t->const_oop()->as_type_array();
ciTypeArray* src_array_type = get_constant_value(kit, str);
// Check encoding of constant string
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) {
assert(str->is_Con(), "String must be constant");
Node* src_array = kit.load_String_value(kit.control(), str);
const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr();
return t->const_oop()->as_type_array()->length();
return get_constant_value(kit, str)->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) {

View file

@ -97,6 +97,9 @@ class PhaseStringOpts : public Phase {
// Returns the length of a constant string
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
void record_dead_node(Node* node);
void remove_dead_nodes();