8149813: Move trusted final field handling from C2 LoadNode::Value to shared code
Reviewed-by: thartmann, kvn
--- a/hotspot/src/share/vm/ci/ciField.cpp Mon Feb 15 18:42:45 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciField.cpp Mon Feb 15 23:45:15 2016 +0300
@@ -211,6 +211,12 @@
// 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() ||
--- a/hotspot/src/share/vm/opto/memnode.cpp Mon Feb 15 18:42:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/memnode.cpp Mon Feb 15 23:45:15 2016 +0300
@@ -1709,38 +1709,10 @@
// 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();
--- a/hotspot/src/share/vm/opto/stringopts.cpp Mon Feb 15 18:42:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/stringopts.cpp Mon Feb 15 23:45:15 2016 +0300
@@ -1552,8 +1552,7 @@
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 @@
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) {
--- a/hotspot/src/share/vm/opto/stringopts.hpp Mon Feb 15 18:42:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/stringopts.hpp Mon Feb 15 23:45:15 2016 +0300
@@ -97,6 +97,9 @@
// 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();