8149813: Move trusted final field handling from C2 LoadNode::Value to shared code
authorshade
Mon, 15 Feb 2016 23:45:15 +0300
changeset 36077 fa6d92de1c70
parent 36076 ef2c34c80771
child 36078 954c49c0ba57
8149813: Move trusted final field handling from C2 LoadNode::Value to shared code Reviewed-by: thartmann, kvn
hotspot/src/share/vm/ci/ciField.cpp
hotspot/src/share/vm/opto/memnode.cpp
hotspot/src/share/vm/opto/stringopts.cpp
hotspot/src/share/vm/opto/stringopts.hpp
--- 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();